mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-19 11:12:43 +00:00
address review feedback
This commit is contained in:
parent
aa55f6daa2
commit
6bd970d585
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
Loading…
Reference in New Issue
Block a user