Normalize bounds fully when checking defaulted types
This commit is contained in:
parent
8ad7bc3f42
commit
83a9dc92d5
@ -1196,8 +1196,6 @@ fn compare_projection_bounds<'tcx>(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let param_env = tcx.param_env(impl_ty.def_id);
|
||||
|
||||
// Given
|
||||
//
|
||||
// impl<A, B> Foo<u32> for (A, B) {
|
||||
@ -1212,6 +1210,36 @@ fn compare_projection_bounds<'tcx>(
|
||||
impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
|
||||
let impl_ty_value = tcx.type_of(impl_ty.def_id);
|
||||
|
||||
let param_env = tcx.param_env(impl_ty.def_id);
|
||||
|
||||
// When checking something like
|
||||
//
|
||||
// trait X { type Y: PartialEq<<Self as X>::Y> }
|
||||
// impl X for T { default type Y = S; }
|
||||
//
|
||||
// We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case
|
||||
// we want <T as X>::Y to normalize to S. This is valid because we are
|
||||
// checking the default value specifically here. Add this equality to the
|
||||
// ParamEnv for normalization specifically.
|
||||
let normalize_param_env = if impl_ty.defaultness.is_final() {
|
||||
// If the associated type is final then normalization can already
|
||||
// do this without the explicit predicate.
|
||||
param_env
|
||||
} else {
|
||||
let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
|
||||
predicates.push(
|
||||
ty::Binder::dummy(ty::ProjectionPredicate {
|
||||
projection_ty: ty::ProjectionTy {
|
||||
item_def_id: trait_ty.def_id,
|
||||
substs: rebased_substs,
|
||||
},
|
||||
ty: impl_ty_value,
|
||||
})
|
||||
.to_predicate(tcx),
|
||||
);
|
||||
ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing, None)
|
||||
};
|
||||
|
||||
// Map the predicate from the trait to the corresponding one for the impl.
|
||||
// For example:
|
||||
//
|
||||
@ -1275,9 +1303,11 @@ fn compare_projection_bounds<'tcx>(
|
||||
_ => bug!("unexepected projection predicate kind: `{:?}`", predicate),
|
||||
};
|
||||
|
||||
debug!("compare_projection_bounds: concrete predicate = {:?}", concrete_ty_predicate);
|
||||
|
||||
let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
|
||||
&mut selcx,
|
||||
param_env,
|
||||
normalize_param_env,
|
||||
normalize_cause.clone(),
|
||||
&concrete_ty_predicate,
|
||||
);
|
||||
|
25
src/test/ui/associated-type-bounds/issue-73818.rs
Normal file
25
src/test/ui/associated-type-bounds/issue-73818.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// Test that associated type bounds are correctly normalized when checking
|
||||
// default associated type values.
|
||||
// check-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(specialization)]
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum Never {}
|
||||
trait Foo {
|
||||
type Assoc: PartialEq; // PartialEq<<Self as Foo>::Assoc>
|
||||
}
|
||||
impl<T> Foo for T {
|
||||
default type Assoc = Never;
|
||||
}
|
||||
|
||||
trait Trait1 {
|
||||
type Selection: PartialEq;
|
||||
}
|
||||
trait Trait2: PartialEq<Self> {}
|
||||
impl<T: Trait2> Trait1 for T {
|
||||
default type Selection = T;
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user