Skip to content

Commit 6bd970d

Browse files
author
Lukas Markeffsky
committed
address review feedback
1 parent aa55f6d commit 6bd970d

File tree

4 files changed

+101
-31
lines changed

4 files changed

+101
-31
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+51-28
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
13821382

13831383
#[extension(pub(super) trait InferCtxtPrivExt<'tcx>)]
13841384
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
1385+
fn can_match_trait(
1386+
&self,
1387+
goal: ty::TraitPredicate<'tcx>,
1388+
assumption: ty::PolyTraitPredicate<'tcx>,
1389+
) -> bool {
1390+
if goal.polarity != assumption.polarity() {
1391+
return false;
1392+
}
1393+
1394+
let trait_goal = goal.trait_ref;
1395+
let trait_assumption = self.instantiate_binder_with_fresh_vars(
1396+
DUMMY_SP,
1397+
infer::BoundRegionConversionTime::HigherRankedType,
1398+
assumption.to_poly_trait_ref(),
1399+
);
1400+
1401+
self.can_eq(ty::ParamEnv::empty(), trait_goal, trait_assumption)
1402+
}
1403+
1404+
fn can_match_projection(
1405+
&self,
1406+
goal: ty::ProjectionPredicate<'tcx>,
1407+
assumption: ty::PolyProjectionPredicate<'tcx>,
1408+
) -> bool {
1409+
let assumption = self.instantiate_binder_with_fresh_vars(
1410+
DUMMY_SP,
1411+
infer::BoundRegionConversionTime::HigherRankedType,
1412+
assumption,
1413+
);
1414+
1415+
let param_env = ty::ParamEnv::empty();
1416+
self.can_eq(param_env, goal.projection_ty, assumption.projection_ty)
1417+
&& self.can_eq(param_env, goal.term, assumption.term)
1418+
}
1419+
13851420
// returns if `cond` not occurring implies that `error` does not occur - i.e., that
13861421
// `error` occurring implies that `cond` occurs.
13871422
fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
@@ -1390,39 +1425,27 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
13901425
}
13911426

13921427
if let Some(error) = error.to_opt_poly_trait_pred() {
1393-
elaborate(self.tcx, std::iter::once(cond))
1394-
.filter_map(|implied| implied.to_opt_poly_trait_pred())
1395-
.any(|implied| {
1396-
if error.polarity() != implied.polarity() {
1397-
return false;
1398-
}
1399-
let error = error.to_poly_trait_ref();
1400-
let implied = implied.to_poly_trait_ref();
1401-
// FIXME: I'm just not taking associated types at all here.
1402-
// Eventually I'll need to implement param-env-aware
1403-
// `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
1404-
let param_env = ty::ParamEnv::empty();
1405-
let is_implied = self.can_sub(param_env, error, implied);
1406-
if is_implied {
1407-
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied);
1408-
}
1409-
is_implied
1410-
})
1428+
self.enter_forall(error, |error| {
1429+
elaborate(self.tcx, std::iter::once(cond))
1430+
.filter_map(|implied| implied.to_opt_poly_trait_pred())
1431+
.any(|implied| {
1432+
let is_implied = self.can_match_trait(error, implied);
1433+
if is_implied {
1434+
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied);
1435+
}
1436+
is_implied
1437+
})
1438+
})
14111439
} else if let Some(error) = error.to_opt_poly_projection_pred() {
14121440
self.enter_forall(error, |error| {
14131441
elaborate(self.tcx, std::iter::once(cond))
14141442
.filter_map(|implied| implied.to_opt_poly_projection_pred())
14151443
.any(|implied| {
1416-
self.enter_forall(implied, |implied| {
1417-
let param_env = ty::ParamEnv::empty();
1418-
let is_implied =
1419-
self.can_eq(param_env, error.projection_ty, implied.projection_ty)
1420-
&& self.can_eq(param_env, error.term, implied.term);
1421-
if is_implied {
1422-
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied);
1423-
}
1424-
is_implied
1425-
})
1444+
let is_implied = self.can_match_projection(error, implied);
1445+
if is_implied {
1446+
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied);
1447+
}
1448+
is_implied
14261449
})
14271450
})
14281451
} else {

compiler/rustc_trait_selection/src/traits/wf.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ enum Elaborate {
235235
///
236236
/// And a super predicate of `TargetTrait` that has any of the following forms:
237237
///
238-
/// 1. `<OtherType as OtherTrait>::Assoc = <TargetType as TargetTrait>::Assoc`
239-
/// 2. `<<TargetType as TargetTrait>::Assoc as OtherTrait>::Assoc = OtherType`
238+
/// 1. `<OtherType as OtherTrait>::Assoc == <TargetType as TargetTrait>::Assoc`
239+
/// 2. `<<TargetType as TargetTrait>::Assoc as OtherTrait>::Assoc == OtherType`
240240
/// 3. `<TargetType as TargetTrait>::Assoc: OtherTrait`
241241
///
242242
/// 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>(
292292
}
293293

294294
// Form 2: A projection obligation for an associated item failed to be met.
295+
// We overwrite the span from above to ensure that a bound like
296+
// `Self::Assoc1: Trait<OtherAssoc = Self::Assoc2>` gets the same
297+
// span for both obligations that it is lowered to.
295298
if let Some(impl_item_span) = ty_to_impl_span(proj.self_ty()) {
296299
cause.span = impl_item_span;
297300
}

tests/ui/trait-bounds/super-assoc-mismatch.rs

+24
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,28 @@ impl BoundOnGat for u8 {
3333
fn trivial_bound() where (): Sub {}
3434
//~^ ERROR the trait bound `(): Sub` is not satisfied
3535

36+
// The following is an edge case where the unsatisfied projection predicate
37+
// `<<u8 as MultiAssoc>::Assoc1<()> as SuperGeneric<u16>>::Assoc == <u8 as MultiAssoc>::Assoc2`
38+
// contains both associated types of `MultiAssoc`. To suppress the error about the unsatisfied
39+
// super projection, the error's span must be equal to the span of the unsatisfied trait error.
40+
trait SuperGeneric<T> {
41+
type Assoc;
42+
}
43+
trait SubGeneric<T>: SuperGeneric<T, Assoc = T> {}
44+
trait MultiAssoc
45+
where
46+
Self::Assoc1<()>: SubGeneric<Self::Assoc2>
47+
{
48+
type Assoc1<T>;
49+
type Assoc2;
50+
}
51+
impl SuperGeneric<u16> for () {
52+
type Assoc = u8;
53+
}
54+
impl MultiAssoc for u8 {
55+
type Assoc1<T> = ();
56+
//~^ ERROR the trait bound `(): SubGeneric<u16>` is not satisfied
57+
type Assoc2 = u16;
58+
}
59+
3660
fn main() {}

tests/ui/trait-bounds/super-assoc-mismatch.stderr

+21-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,26 @@ LL | trait Sub: Super<Assoc = u16> {}
8080
= help: see issue #48214
8181
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
8282

83-
error: aborting due to 5 previous errors
83+
error[E0277]: the trait bound `(): SubGeneric<u16>` is not satisfied
84+
--> $DIR/super-assoc-mismatch.rs:55:22
85+
|
86+
LL | type Assoc1<T> = ();
87+
| ^^ the trait `SubGeneric<u16>` is not implemented for `()`, which is required by `<u8 as MultiAssoc>::Assoc1<()>: SubGeneric<<u8 as MultiAssoc>::Assoc2>`
88+
|
89+
help: this trait has no implementations, consider adding one
90+
--> $DIR/super-assoc-mismatch.rs:43:1
91+
|
92+
LL | trait SubGeneric<T>: SuperGeneric<T, Assoc = T> {}
93+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
94+
note: required by a bound in `MultiAssoc`
95+
--> $DIR/super-assoc-mismatch.rs:46:23
96+
|
97+
LL | trait MultiAssoc
98+
| ---------- required by a bound in this trait
99+
LL | where
100+
LL | Self::Assoc1<()>: SubGeneric<Self::Assoc2>
101+
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MultiAssoc`
102+
103+
error: aborting due to 6 previous errors
84104

85105
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)