mirror of
https://github.com/rust-lang/rust
synced 2024-09-15 22:50:55 +00:00
coherence: don't add hidden types for opaques
we can otherwise assign a hidden type to the opaque which causes ICE if we don't use `take_opaque_types` during coherence. This is annoying so I didn't bother. Added a test showing the behavior this prevents.
This commit is contained in:
parent
200ed9f8cd
commit
0a6ae29fe8
|
@ -533,17 +533,29 @@ fn register_hidden_type(
|
|||
// these are the same span, but not in cases like `-> (impl
|
||||
// Foo, impl Bar)`.
|
||||
let span = cause.span;
|
||||
let prev = self.inner.borrow_mut().opaque_types().register(
|
||||
opaque_type_key,
|
||||
OpaqueHiddenType { ty: hidden_ty, span },
|
||||
origin,
|
||||
);
|
||||
let mut obligations = if let Some(prev) = prev {
|
||||
self.at(&cause, param_env)
|
||||
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
|
||||
.obligations
|
||||
let mut obligations = if self.intercrate {
|
||||
// During intercrate we do not define opaque types but instead always
|
||||
// force ambiguity unless the hidden type is known to not implement
|
||||
// our trait.
|
||||
vec![traits::Obligation::new(
|
||||
self.tcx,
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::PredicateKind::Ambiguous,
|
||||
)]
|
||||
} else {
|
||||
Vec::new()
|
||||
let prev = self.inner.borrow_mut().opaque_types().register(
|
||||
opaque_type_key,
|
||||
OpaqueHiddenType { ty: hidden_ty, span },
|
||||
origin,
|
||||
);
|
||||
if let Some(prev) = prev {
|
||||
self.at(&cause, param_env)
|
||||
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
|
||||
.obligations
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
self.add_item_bounds_for_hidden_type(
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// When checking whether these two impls overlap, we could detect that we
|
||||
// would require the hidden type of `TAIT` to be equal to both `u32` and `i32`
|
||||
// and therefore accept them as disjoint. That is annoying to implement with
|
||||
// the current system because we would have to add the following to each
|
||||
// returning branch in coherence.
|
||||
//
|
||||
// let _ = infcx.take_opaque_types();
|
||||
//
|
||||
// @lcnr: Because of this I decided to not bother and cause this to fail instead.
|
||||
// In the future we can definitely modify the compiler to accept this
|
||||
// again.
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Trait {}
|
||||
|
||||
type TAIT = impl Sized;
|
||||
|
||||
impl Trait for (TAIT, TAIT) {}
|
||||
|
||||
impl Trait for (u32, i32) {}
|
||||
//~^ ERROR conflicting implementations of trait `Trait` for type `(TAIT, TAIT)`
|
||||
|
||||
fn define() -> TAIT {}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,12 @@
|
|||
error[E0119]: conflicting implementations of trait `Trait` for type `(TAIT, TAIT)`
|
||||
--> $DIR/coherence_different_hidden_ty.rs:20:1
|
||||
|
|
||||
LL | impl Trait for (TAIT, TAIT) {}
|
||||
| --------------------------- first implementation here
|
||||
LL |
|
||||
LL | impl Trait for (u32, i32) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(TAIT, TAIT)`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
Loading…
Reference in a new issue