address review feedback

This commit is contained in:
Lukas Markeffsky 2024-03-04 21:06:16 +01:00
parent aa55f6daa2
commit 6bd970d585
4 changed files with 101 additions and 31 deletions

View File

@ -1382,6 +1382,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
#[extension(pub(super) trait InferCtxtPrivExt<'tcx>)]
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn can_match_trait(
&self,
goal: ty::TraitPredicate<'tcx>,
assumption: ty::PolyTraitPredicate<'tcx>,
) -> bool {
if goal.polarity != assumption.polarity() {
return false;
}
let trait_goal = goal.trait_ref;
let trait_assumption = self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
infer::BoundRegionConversionTime::HigherRankedType,
assumption.to_poly_trait_ref(),
);
self.can_eq(ty::ParamEnv::empty(), trait_goal, trait_assumption)
}
fn can_match_projection(
&self,
goal: ty::ProjectionPredicate<'tcx>,
assumption: ty::PolyProjectionPredicate<'tcx>,
) -> bool {
let assumption = self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
infer::BoundRegionConversionTime::HigherRankedType,
assumption,
);
let param_env = ty::ParamEnv::empty();
self.can_eq(param_env, goal.projection_ty, assumption.projection_ty)
&& self.can_eq(param_env, goal.term, assumption.term)
}
// returns if `cond` not occurring implies that `error` does not occur - i.e., that
// `error` occurring implies that `cond` occurs.
fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
@ -1390,39 +1425,27 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
if let Some(error) = error.to_opt_poly_trait_pred() {
elaborate(self.tcx, std::iter::once(cond))
.filter_map(|implied| implied.to_opt_poly_trait_pred())
.any(|implied| {
if error.polarity() != implied.polarity() {
return false;
}
let error = error.to_poly_trait_ref();
let implied = implied.to_poly_trait_ref();
// FIXME: I'm just not taking associated types at all here.
// Eventually I'll need to implement param-env-aware
// `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
let param_env = ty::ParamEnv::empty();
let is_implied = self.can_sub(param_env, error, implied);
if is_implied {
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied);
}
is_implied
})
self.enter_forall(error, |error| {
elaborate(self.tcx, std::iter::once(cond))
.filter_map(|implied| implied.to_opt_poly_trait_pred())
.any(|implied| {
let is_implied = self.can_match_trait(error, implied);
if is_implied {
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied);
}
is_implied
})
})
} else if let Some(error) = error.to_opt_poly_projection_pred() {
self.enter_forall(error, |error| {
elaborate(self.tcx, std::iter::once(cond))
.filter_map(|implied| implied.to_opt_poly_projection_pred())
.any(|implied| {
self.enter_forall(implied, |implied| {
let param_env = ty::ParamEnv::empty();
let is_implied =
self.can_eq(param_env, error.projection_ty, implied.projection_ty)
&& self.can_eq(param_env, error.term, implied.term);
if is_implied {
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied);
}
is_implied
})
let is_implied = self.can_match_projection(error, implied);
if is_implied {
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied);
}
is_implied
})
})
} else {

View File

@ -235,8 +235,8 @@ enum Elaborate {
///
/// And a super predicate of `TargetTrait` that has any of the following forms:
///
/// 1. `<OtherType as OtherTrait>::Assoc = <TargetType as TargetTrait>::Assoc`
/// 2. `<<TargetType as TargetTrait>::Assoc as OtherTrait>::Assoc = OtherType`
/// 1. `<OtherType as OtherTrait>::Assoc == <TargetType as TargetTrait>::Assoc`
/// 2. `<<TargetType as TargetTrait>::Assoc as OtherTrait>::Assoc == OtherType`
/// 3. `<TargetType as TargetTrait>::Assoc: OtherTrait`
///
/// Replace the span of the cause with the span of the associated item:
@ -292,6 +292,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
}
// Form 2: A projection obligation for an associated item failed to be met.
// We overwrite the span from above to ensure that a bound like
// `Self::Assoc1: Trait<OtherAssoc = Self::Assoc2>` gets the same
// span for both obligations that it is lowered to.
if let Some(impl_item_span) = ty_to_impl_span(proj.self_ty()) {
cause.span = impl_item_span;
}

View File

@ -33,4 +33,28 @@ impl BoundOnGat for u8 {
fn trivial_bound() where (): Sub {}
//~^ ERROR the trait bound `(): Sub` is not satisfied
// The following is an edge case where the unsatisfied projection predicate
// `<<u8 as MultiAssoc>::Assoc1<()> as SuperGeneric<u16>>::Assoc == <u8 as MultiAssoc>::Assoc2`
// contains both associated types of `MultiAssoc`. To suppress the error about the unsatisfied
// super projection, the error's span must be equal to the span of the unsatisfied trait error.
trait SuperGeneric<T> {
type Assoc;
}
trait SubGeneric<T>: SuperGeneric<T, Assoc = T> {}
trait MultiAssoc
where
Self::Assoc1<()>: SubGeneric<Self::Assoc2>
{
type Assoc1<T>;
type Assoc2;
}
impl SuperGeneric<u16> for () {
type Assoc = u8;
}
impl MultiAssoc for u8 {
type Assoc1<T> = ();
//~^ ERROR the trait bound `(): SubGeneric<u16>` is not satisfied
type Assoc2 = u16;
}
fn main() {}

View File

@ -80,6 +80,26 @@ LL | trait Sub: Super<Assoc = u16> {}
= help: see issue #48214
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
error: aborting due to 5 previous errors
error[E0277]: the trait bound `(): SubGeneric<u16>` is not satisfied
--> $DIR/super-assoc-mismatch.rs:55:22
|
LL | type Assoc1<T> = ();
| ^^ the trait `SubGeneric<u16>` is not implemented for `()`, which is required by `<u8 as MultiAssoc>::Assoc1<()>: SubGeneric<<u8 as MultiAssoc>::Assoc2>`
|
help: this trait has no implementations, consider adding one
--> $DIR/super-assoc-mismatch.rs:43:1
|
LL | trait SubGeneric<T>: SuperGeneric<T, Assoc = T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `MultiAssoc`
--> $DIR/super-assoc-mismatch.rs:46:23
|
LL | trait MultiAssoc
| ---------- required by a bound in this trait
LL | where
LL | Self::Assoc1<()>: SubGeneric<Self::Assoc2>
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MultiAssoc`
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0277`.