Skip to content

Commit 8528387

Browse files
Be better at reporting alias errors
1 parent fd2038d commit 8528387

39 files changed

+237
-420
lines changed

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ where
983983
hidden_ty,
984984
&mut goals,
985985
);
986-
self.add_goals(GoalSource::Misc, goals);
986+
self.add_goals(GoalSource::AliasWellFormed, goals);
987987
}
988988

989989
// Do something for each opaque/hidden pair defined with `def_id` in the

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ where
3737
match normalize_result {
3838
Ok(res) => Ok(res),
3939
Err(NoSolution) => {
40-
let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal;
41-
self.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?;
42-
self.add_rigid_constraints(param_env, alias)?;
43-
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
40+
self.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
41+
let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal;
42+
this.add_rigid_constraints(param_env, alias)?;
43+
this.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?;
44+
this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
45+
})
4446
}
4547
}
4648
}
@@ -59,11 +61,13 @@ where
5961
param_env: I::ParamEnv,
6062
rigid_alias: ty::AliasTerm<I>,
6163
) -> Result<(), NoSolution> {
62-
match rigid_alias.kind(self.cx()) {
63-
// Projections are rigid only if their trait ref holds.
64+
let cx = self.cx();
65+
match rigid_alias.kind(cx) {
66+
// Projections are rigid only if their trait ref holds,
67+
// and the GAT where-clauses hold.
6468
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
65-
let trait_ref = rigid_alias.trait_ref(self.cx());
66-
self.add_goal(GoalSource::Misc, Goal::new(self.cx(), param_env, trait_ref));
69+
let trait_ref = rigid_alias.trait_ref(cx);
70+
self.add_goal(GoalSource::AliasWellFormed, Goal::new(cx, param_env, trait_ref));
6771
Ok(())
6872
}
6973
ty::AliasTermKind::OpaqueTy => {

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_middle::bug;
1313
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1414
use rustc_middle::ty::{self, TyCtxt};
1515
use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _};
16-
use tracing::instrument;
16+
use tracing::{instrument, trace};
1717

1818
use super::Certainty;
1919
use super::delegate::SolverDelegate;
@@ -402,6 +402,7 @@ impl<'tcx> BestObligation<'tcx> {
402402
nested_goal.source(),
403403
GoalSource::ImplWhereBound
404404
| GoalSource::InstantiateHigherRanked
405+
| GoalSource::AliasWellFormed
405406
) && match self.consider_ambiguities {
406407
true => {
407408
matches!(
@@ -416,6 +417,13 @@ impl<'tcx> BestObligation<'tcx> {
416417
})
417418
});
418419
}
420+
421+
// Prefer a non-rigid candidate if there is one.
422+
if candidates.len() > 1 {
423+
candidates.retain(|candidate| {
424+
!matches!(candidate.kind(), inspect::ProbeKind::RigidAlias { .. })
425+
});
426+
}
419427
}
420428
}
421429

@@ -430,8 +438,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
430438
self.obligation.cause.span
431439
}
432440

441+
#[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))]
433442
fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
434443
let candidates = self.non_trivial_candidates(goal);
444+
trace!(candidates = ?candidates.iter().map(|c| c.kind()).collect::<Vec<_>>());
445+
435446
let [candidate] = candidates.as_slice() else {
436447
return ControlFlow::Break(self.obligation.clone());
437448
};
@@ -470,6 +481,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
470481

471482
let mut impl_where_bound_count = 0;
472483
for nested_goal in candidate.instantiate_nested_goals(self.span()) {
484+
trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
485+
473486
let make_obligation = |cause| Obligation {
474487
cause,
475488
param_env: nested_goal.goal().param_env,
@@ -496,7 +509,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
496509
(_, GoalSource::InstantiateHigherRanked) => {
497510
obligation = self.obligation.clone();
498511
}
499-
(ChildMode::PassThrough, _) => {
512+
(ChildMode::PassThrough, _) | (_, GoalSource::AliasWellFormed) => {
500513
obligation = make_obligation(self.obligation.cause.clone());
501514
}
502515
}

compiler/rustc_trait_selection/src/solve/inspect/analyse.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
292292
| inspect::ProbeKind::Root { .. }
293293
| inspect::ProbeKind::TryNormalizeNonRigid { .. }
294294
| inspect::ProbeKind::TraitCandidate { .. }
295-
| inspect::ProbeKind::OpaqueTypeStorageLookup { .. } => {
295+
| inspect::ProbeKind::OpaqueTypeStorageLookup { .. }
296+
| inspect::ProbeKind::RigidAlias { .. } => {
296297
// Nested probes have to prove goals added in their parent
297298
// but do not leak them, so we truncate the added goals
298299
// afterwards.
@@ -316,7 +317,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
316317
inspect::ProbeKind::Root { result }
317318
| inspect::ProbeKind::TryNormalizeNonRigid { result }
318319
| inspect::ProbeKind::TraitCandidate { source: _, result }
319-
| inspect::ProbeKind::OpaqueTypeStorageLookup { result } => {
320+
| inspect::ProbeKind::OpaqueTypeStorageLookup { result }
321+
| inspect::ProbeKind::RigidAlias { result } => {
320322
// We only add a candidate if `shallow_certainty` was set, which means
321323
// that we ended up calling `evaluate_added_goals_and_make_canonical_response`.
322324
if let Some(shallow_certainty) = shallow_certainty {

compiler/rustc_trait_selection/src/solve/select.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ fn to_selection<'tcx>(
177177
| ProbeKind::UpcastProjectionCompatibility
178178
| ProbeKind::OpaqueTypeStorageLookup { result: _ }
179179
| ProbeKind::Root { result: _ }
180-
| ProbeKind::ShadowedEnvProbing => {
180+
| ProbeKind::ShadowedEnvProbing
181+
| ProbeKind::RigidAlias { result: _ } => {
181182
span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind())
182183
}
183184
})

compiler/rustc_type_ir/src/solve/inspect.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,6 @@ pub enum ProbeKind<I: Interner> {
135135
ShadowedEnvProbing,
136136
/// Try to unify an opaque type with an existing key in the storage.
137137
OpaqueTypeStorageLookup { result: QueryResult<I> },
138+
/// Checking that a rigid alias is well-formed.
139+
RigidAlias { result: QueryResult<I> },
138140
}

compiler/rustc_type_ir/src/solve/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ pub enum GoalSource {
130130
ImplWhereBound,
131131
/// Instantiating a higher-ranked goal and re-proving it.
132132
InstantiateHigherRanked,
133+
/// Predicate required for an alias projection to be well-formed.
134+
/// This is used in two places: projecting to an opaque whose hidden type
135+
/// is already registered in the opaque type storage, and for rigid projections.
136+
AliasWellFormed,
133137
}
134138

135139
#[derive_where(Clone; I: Interner, Goal<I, P>: Clone)]

tests/ui/associated-types/defaults-unsound-62211-1.next.stderr

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,17 @@ help: consider further restricting `Self`
3131
LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
3232
| +++++++++++++++++++++++++
3333

34-
error[E0271]: type mismatch resolving `<Self as Deref>::Target normalizes-to <Self as Deref>::Target`
35-
--> $DIR/defaults-unsound-62211-1.rs:24:96
36-
|
37-
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
38-
| ^^^^ types differ
39-
|
40-
note: required by a bound in `UncheckedCopy::Output`
41-
--> $DIR/defaults-unsound-62211-1.rs:24:31
42-
|
43-
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
44-
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
45-
4634
error[E0277]: the trait bound `Self: Deref` is not satisfied
4735
--> $DIR/defaults-unsound-62211-1.rs:24:96
4836
|
4937
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
5038
| ^^^^ the trait `Deref` is not implemented for `Self`
5139
|
5240
note: required by a bound in `UncheckedCopy::Output`
53-
--> $DIR/defaults-unsound-62211-1.rs:24:25
41+
--> $DIR/defaults-unsound-62211-1.rs:24:31
5442
|
5543
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
56-
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
44+
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
5745
help: consider further restricting `Self`
5846
|
5947
LL | trait UncheckedCopy: Sized + Deref {
@@ -75,7 +63,6 @@ help: consider further restricting `Self`
7563
LL | trait UncheckedCopy: Sized + Copy {
7664
| ++++++
7765

78-
error: aborting due to 5 previous errors
66+
error: aborting due to 4 previous errors
7967

80-
Some errors have detailed explanations: E0271, E0277.
81-
For more information about an error, try `rustc --explain E0271`.
68+
For more information about this error, try `rustc --explain E0277`.

tests/ui/associated-types/defaults-unsound-62211-2.next.stderr

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,17 @@ help: consider further restricting `Self`
3131
LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
3232
| +++++++++++++++++++++++++
3333

34-
error[E0271]: type mismatch resolving `<Self as Deref>::Target normalizes-to <Self as Deref>::Target`
35-
--> $DIR/defaults-unsound-62211-2.rs:24:96
36-
|
37-
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
38-
| ^^^^ types differ
39-
|
40-
note: required by a bound in `UncheckedCopy::Output`
41-
--> $DIR/defaults-unsound-62211-2.rs:24:31
42-
|
43-
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
44-
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
45-
4634
error[E0277]: the trait bound `Self: Deref` is not satisfied
4735
--> $DIR/defaults-unsound-62211-2.rs:24:96
4836
|
4937
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
5038
| ^^^^ the trait `Deref` is not implemented for `Self`
5139
|
5240
note: required by a bound in `UncheckedCopy::Output`
53-
--> $DIR/defaults-unsound-62211-2.rs:24:25
41+
--> $DIR/defaults-unsound-62211-2.rs:24:31
5442
|
5543
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
56-
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
44+
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
5745
help: consider further restricting `Self`
5846
|
5947
LL | trait UncheckedCopy: Sized + Deref {
@@ -75,7 +63,6 @@ help: consider further restricting `Self`
7563
LL | trait UncheckedCopy: Sized + Copy {
7664
| ++++++
7765

78-
error: aborting due to 5 previous errors
66+
error: aborting due to 4 previous errors
7967

80-
Some errors have detailed explanations: E0271, E0277.
81-
For more information about an error, try `rustc --explain E0271`.
68+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
error[E0271]: type mismatch resolving `<<T as SubEncoder>::ActualSize as Add>::Output normalizes-to <<T as SubEncoder>::ActualSize as Add>::Output`
2-
--> $DIR/issue-54108.rs:23:17
3-
|
4-
LL | type Size = <Self as SubEncoder>::ActualSize;
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
6-
|
7-
note: required by a bound in `Encoder::Size`
8-
--> $DIR/issue-54108.rs:8:20
9-
|
10-
LL | type Size: Add<Output = Self::Size>;
11-
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
12-
131
error[E0277]: cannot add `<T as SubEncoder>::ActualSize` to `<T as SubEncoder>::ActualSize`
142
--> $DIR/issue-54108.rs:23:17
153
|
@@ -18,16 +6,15 @@ LL | type Size = <Self as SubEncoder>::ActualSize;
186
|
197
= help: the trait `Add` is not implemented for `<T as SubEncoder>::ActualSize`
208
note: required by a bound in `Encoder::Size`
21-
--> $DIR/issue-54108.rs:8:16
9+
--> $DIR/issue-54108.rs:8:20
2210
|
2311
LL | type Size: Add<Output = Self::Size>;
24-
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
12+
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
2513
help: consider further restricting the associated type
2614
|
2715
LL | T: SubEncoder, <T as SubEncoder>::ActualSize: Add
2816
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2917

30-
error: aborting due to 2 previous errors
18+
error: aborting due to 1 previous error
3119

32-
Some errors have detailed explanations: E0271, E0277.
33-
For more information about an error, try `rustc --explain E0271`.
20+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)