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
3 changed files with 59 additions and 10 deletions
|
@ -533,17 +533,29 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
// these are the same span, but not in cases like `-> (impl
|
// these are the same span, but not in cases like `-> (impl
|
||||||
// Foo, impl Bar)`.
|
// Foo, impl Bar)`.
|
||||||
let span = cause.span;
|
let span = cause.span;
|
||||||
let prev = self.inner.borrow_mut().opaque_types().register(
|
let mut obligations = if self.intercrate {
|
||||||
opaque_type_key,
|
// During intercrate we do not define opaque types but instead always
|
||||||
OpaqueHiddenType { ty: hidden_ty, span },
|
// force ambiguity unless the hidden type is known to not implement
|
||||||
origin,
|
// our trait.
|
||||||
);
|
vec![traits::Obligation::new(
|
||||||
let mut obligations = if let Some(prev) = prev {
|
self.tcx,
|
||||||
self.at(&cause, param_env)
|
cause.clone(),
|
||||||
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
|
param_env,
|
||||||
.obligations
|
ty::PredicateKind::Ambiguous,
|
||||||
|
)]
|
||||||
} else {
|
} 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(
|
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…
Add table
Add a link
Reference in a new issue