Fix inherent impls on negative coherence
This commit is contained in:
parent
a8adf7685a
commit
89fdb62331
2 changed files with 87 additions and 41 deletions
|
@ -300,12 +300,12 @@ fn negative_impl<'cx, 'tcx>(
|
||||||
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
|
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
|
||||||
let tcx = selcx.infcx().tcx;
|
let tcx = selcx.infcx().tcx;
|
||||||
|
|
||||||
// create a parameter environment corresponding to a (placeholder) instantiation of impl1
|
|
||||||
let impl1_env = tcx.param_env(impl1_def_id);
|
|
||||||
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
|
|
||||||
|
|
||||||
// Create an infcx, taking the predicates of impl1 as assumptions:
|
// Create an infcx, taking the predicates of impl1 as assumptions:
|
||||||
tcx.infer_ctxt().enter(|infcx| {
|
tcx.infer_ctxt().enter(|infcx| {
|
||||||
|
// create a parameter environment corresponding to a (placeholder) instantiation of impl1
|
||||||
|
let impl1_env = tcx.param_env(impl1_def_id);
|
||||||
|
|
||||||
|
if let Some(impl1_trait_ref) = tcx.impl_trait_ref(impl1_def_id) {
|
||||||
// Normalize the trait reference. The WF rules ought to ensure
|
// Normalize the trait reference. The WF rules ought to ensure
|
||||||
// that this always succeeds.
|
// that this always succeeds.
|
||||||
let impl1_trait_ref = match traits::fully_normalize(
|
let impl1_trait_ref = match traits::fully_normalize(
|
||||||
|
@ -330,8 +330,7 @@ fn negative_impl<'cx, 'tcx>(
|
||||||
// do the impls unify? If not, not disjoint.
|
// do the impls unify? If not, not disjoint.
|
||||||
let Ok(InferOk { obligations: more_obligations, .. }) = infcx
|
let Ok(InferOk { obligations: more_obligations, .. }) = infcx
|
||||||
.at(&ObligationCause::dummy(), impl1_env)
|
.at(&ObligationCause::dummy(), impl1_env)
|
||||||
.eq(impl1_trait_ref, impl2_trait_ref)
|
.eq(impl1_trait_ref, impl2_trait_ref) else {
|
||||||
else {
|
|
||||||
debug!(
|
debug!(
|
||||||
"explicit_disjoint: {:?} does not unify with {:?}",
|
"explicit_disjoint: {:?} does not unify with {:?}",
|
||||||
impl1_trait_ref, impl2_trait_ref
|
impl1_trait_ref, impl2_trait_ref
|
||||||
|
@ -350,6 +349,31 @@ fn negative_impl<'cx, 'tcx>(
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let ty1 = tcx.type_of(impl1_def_id);
|
||||||
|
let ty2 = tcx.type_of(impl2_def_id);
|
||||||
|
|
||||||
|
let Ok(InferOk { obligations, .. }) = infcx
|
||||||
|
.at(&ObligationCause::dummy(), impl1_env)
|
||||||
|
.eq(ty1, ty2) else {
|
||||||
|
debug!(
|
||||||
|
"explicit_disjoint: {:?} does not unify with {:?}",
|
||||||
|
ty1, ty2
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let opt_failing_obligation = obligations
|
||||||
|
.into_iter()
|
||||||
|
.find(|o| negative_impl_exists(selcx, impl1_env, impl1_def_id, o));
|
||||||
|
|
||||||
|
if let Some(failing_obligation) = opt_failing_obligation {
|
||||||
|
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
22
src/test/ui/coherence/coherence-negative-inherent.rs
Normal file
22
src/test/ui/coherence/coherence-negative-inherent.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(negative_impls)]
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
#![feature(with_negative_coherence)]
|
||||||
|
|
||||||
|
#[rustc_strict_coherence]
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
impl !Foo for u32 {}
|
||||||
|
|
||||||
|
struct MyStruct<T>(T);
|
||||||
|
|
||||||
|
impl<T: Foo> MyStruct<T> {
|
||||||
|
fn method(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MyStruct<u32> {
|
||||||
|
fn method(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue