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

+1-1
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

+12-8
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

+15-2
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

+4-2
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

+2-1
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

+2
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

+4
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

+4-17
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

+4-17
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`.
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`.

tests/ui/for/issue-20605.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@
44

55
fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
66
for item in *things { *item = 0 }
7-
//[current]~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
8-
//[next]~^^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
9-
//[next]~| ERROR type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
10-
11-
// FIXME(-Znext-solver): these error messages are horrible and have to be
12-
// improved before we stabilize the new solver.
7+
//~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
138
}
149

1510
fn main() {}

tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0283]: type annotations needed
2-
--> $DIR/ambig-hr-projection-issue-93340.rs:16:5
2+
--> $DIR/ambig-hr-projection-issue-93340.rs:17:5
33
|
44
LL | cmp_eq
55
| ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`
@@ -15,14 +15,16 @@ help: consider specifying the generic arguments
1515
LL | cmp_eq::<A, B, O>
1616
| +++++++++++
1717

18-
error[E0271]: type mismatch resolving `build_expression<A, B, O>::{opaque#0} normalizes-to _`
18+
error[E0277]: expected a `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure, found `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<O, _, O>}`
1919
--> $DIR/ambig-hr-projection-issue-93340.rs:14:1
2020
|
2121
LL | / fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
2222
LL | | ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
23-
| |_________________________________________________^ types differ
23+
| |_________________________________________________^ expected an `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure, found `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<O, _, O>}`
24+
|
25+
= help: the trait `for<'a, 'b> Fn(<A as Scalar>::RefType<'a>, <B as Scalar>::RefType<'b>)` is not implemented for fn item `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<O, _, O>}`
2426

2527
error: aborting due to 2 previous errors
2628

27-
Some errors have detailed explanations: E0271, E0283.
28-
For more information about an error, try `rustc --explain E0271`.
29+
Some errors have detailed explanations: E0277, E0283.
30+
For more information about an error, try `rustc --explain E0277`.

tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0283]: type annotations needed
2-
--> $DIR/ambig-hr-projection-issue-93340.rs:16:5
2+
--> $DIR/ambig-hr-projection-issue-93340.rs:17:5
33
|
44
LL | cmp_eq
55
| ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`

tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefT
1313

1414
fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
1515
) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
16+
//[next]~^^ expected a `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure
1617
cmp_eq
1718
//~^ ERROR type annotations needed
1819
}

tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ struct W<T>(T);
1414
// `usize: Foo` doesn't hold. Therefore we ICE, because we don't expect to still
1515
// encounter weak types in `assemble_alias_bound_candidates_recur`.
1616
fn hello(_: W<A<usize>>) {}
17-
//~^ ERROR the size for values of type `A<usize>` cannot be known at compilation time
17+
//~^ ERROR the trait bound `usize: Foo` is not satisfied
18+
//~| ERROR the trait bound `usize: Foo` is not satisfied
19+
//~| ERROR the trait bound `usize: Foo` is not satisfied
1820

1921
fn main() {}

tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr

+24-14
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,42 @@ LL | #![feature(lazy_type_alias)]
77
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
88
= note: `#[warn(incomplete_features)]` on by default
99

10-
error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
10+
error[E0277]: the trait bound `usize: Foo` is not satisfied
1111
--> $DIR/alias-bounds-when-not-wf.rs:16:13
1212
|
1313
LL | fn hello(_: W<A<usize>>) {}
14-
| ^^^^^^^^^^^ types differ
15-
16-
error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
17-
--> $DIR/alias-bounds-when-not-wf.rs:16:10
14+
| ^^^^^^^^^^^ the trait `Foo` is not implemented for `usize`
1815
|
19-
LL | fn hello(_: W<A<usize>>) {}
20-
| ^ types differ
16+
help: this trait has no implementations, consider adding one
17+
--> $DIR/alias-bounds-when-not-wf.rs:6:1
18+
|
19+
LL | trait Foo {}
20+
| ^^^^^^^^^
2121

22-
error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
22+
error[E0277]: the trait bound `usize: Foo` is not satisfied
2323
--> $DIR/alias-bounds-when-not-wf.rs:16:10
2424
|
2525
LL | fn hello(_: W<A<usize>>) {}
26-
| ^ types differ
26+
| ^ the trait `Foo` is not implemented for `usize`
2727
|
28-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
28+
help: this trait has no implementations, consider adding one
29+
--> $DIR/alias-bounds-when-not-wf.rs:6:1
30+
|
31+
LL | trait Foo {}
32+
| ^^^^^^^^^
2933

30-
error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
34+
error[E0277]: the trait bound `usize: Foo` is not satisfied
3135
--> $DIR/alias-bounds-when-not-wf.rs:16:1
3236
|
3337
LL | fn hello(_: W<A<usize>>) {}
34-
| ^^^^^^^^^^^^^^^^^^^^^^^^ types differ
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `usize`
39+
|
40+
help: this trait has no implementations, consider adding one
41+
--> $DIR/alias-bounds-when-not-wf.rs:6:1
42+
|
43+
LL | trait Foo {}
44+
| ^^^^^^^^^
3545

36-
error: aborting due to 4 previous errors; 1 warning emitted
46+
error: aborting due to 3 previous errors; 1 warning emitted
3747

38-
For more information about this error, try `rustc --explain E0271`.
48+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)