Skip to content

Commit

Permalink
Be better at reporting alias errors
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Oct 16, 2024
1 parent d634cb8 commit c914388
Show file tree
Hide file tree
Showing 39 changed files with 237 additions and 420 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ where
hidden_ty,
&mut goals,
);
self.add_goals(GoalSource::Misc, goals);
self.add_goals(GoalSource::AliasWellFormed, goals);
}

// Do something for each opaque/hidden pair defined with `def_id` in the
Expand Down
20 changes: 12 additions & 8 deletions compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ where
match normalize_result {
Ok(res) => Ok(res),
Err(NoSolution) => {
let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal;
self.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?;
self.add_rigid_constraints(param_env, alias)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
self.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal;
this.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?;
this.add_rigid_constraints(param_env, alias)?;
this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
}
}
Expand All @@ -59,11 +61,13 @@ where
param_env: I::ParamEnv,
rigid_alias: ty::AliasTerm<I>,
) -> Result<(), NoSolution> {
match rigid_alias.kind(self.cx()) {
// Projections are rigid only if their trait ref holds.
let cx = self.cx();
match rigid_alias.kind(cx) {
// Projections are rigid only if their trait ref holds,
// and the GAT where-clauses hold.
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
let trait_ref = rigid_alias.trait_ref(self.cx());
self.add_goal(GoalSource::Misc, Goal::new(self.cx(), param_env, trait_ref));
let trait_ref = rigid_alias.trait_ref(cx);
self.add_goal(GoalSource::AliasWellFormed, Goal::new(cx, param_env, trait_ref));
Ok(())
}
ty::AliasTermKind::OpaqueTy => {
Expand Down
17 changes: 15 additions & 2 deletions compiler/rustc_trait_selection/src/solve/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rustc_middle::bug;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, TyCtxt};
use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _};
use tracing::instrument;
use tracing::{instrument, trace};

use super::Certainty;
use super::delegate::SolverDelegate;
Expand Down Expand Up @@ -402,6 +402,7 @@ impl<'tcx> BestObligation<'tcx> {
nested_goal.source(),
GoalSource::ImplWhereBound
| GoalSource::InstantiateHigherRanked
| GoalSource::AliasWellFormed
) && match self.consider_ambiguities {
true => {
matches!(
Expand All @@ -416,6 +417,13 @@ impl<'tcx> BestObligation<'tcx> {
})
});
}

// Prefer a non-rigid candidate if there is one.
if candidates.len() > 1 {
candidates.retain(|candidate| {
!matches!(candidate.kind(), inspect::ProbeKind::RigidAlias { .. })
});
}
}
}

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

#[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))]
fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
let candidates = self.non_trivial_candidates(goal);
trace!(candidates = ?candidates.iter().map(|c| c.kind()).collect::<Vec<_>>());

let [candidate] = candidates.as_slice() else {
return ControlFlow::Break(self.obligation.clone());
};
Expand Down Expand Up @@ -470,6 +481,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {

let mut impl_where_bound_count = 0;
for nested_goal in candidate.instantiate_nested_goals(self.span()) {
trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));

let make_obligation = |cause| Obligation {
cause,
param_env: nested_goal.goal().param_env,
Expand All @@ -496,7 +509,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
(_, GoalSource::InstantiateHigherRanked) => {
obligation = self.obligation.clone();
}
(ChildMode::PassThrough, _) => {
(ChildMode::PassThrough, _) | (_, GoalSource::AliasWellFormed) => {
obligation = make_obligation(self.obligation.cause.clone());
}
}
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
| inspect::ProbeKind::Root { .. }
| inspect::ProbeKind::TryNormalizeNonRigid { .. }
| inspect::ProbeKind::TraitCandidate { .. }
| inspect::ProbeKind::OpaqueTypeStorageLookup { .. } => {
| inspect::ProbeKind::OpaqueTypeStorageLookup { .. }
| inspect::ProbeKind::RigidAlias { .. } => {
// Nested probes have to prove goals added in their parent
// but do not leak them, so we truncate the added goals
// afterwards.
Expand All @@ -316,7 +317,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
inspect::ProbeKind::Root { result }
| inspect::ProbeKind::TryNormalizeNonRigid { result }
| inspect::ProbeKind::TraitCandidate { source: _, result }
| inspect::ProbeKind::OpaqueTypeStorageLookup { result } => {
| inspect::ProbeKind::OpaqueTypeStorageLookup { result }
| inspect::ProbeKind::RigidAlias { result } => {
// We only add a candidate if `shallow_certainty` was set, which means
// that we ended up calling `evaluate_added_goals_and_make_canonical_response`.
if let Some(shallow_certainty) = shallow_certainty {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_trait_selection/src/solve/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ fn to_selection<'tcx>(
| ProbeKind::UpcastProjectionCompatibility
| ProbeKind::OpaqueTypeStorageLookup { result: _ }
| ProbeKind::Root { result: _ }
| ProbeKind::ShadowedEnvProbing => {
| ProbeKind::ShadowedEnvProbing
| ProbeKind::RigidAlias { result: _ } => {
span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind())
}
})
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_type_ir/src/solve/inspect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,6 @@ pub enum ProbeKind<I: Interner> {
ShadowedEnvProbing,
/// Try to unify an opaque type with an existing key in the storage.
OpaqueTypeStorageLookup { result: QueryResult<I> },
/// Checking that a rigid alias is well-formed.
RigidAlias { result: QueryResult<I> },
}
4 changes: 4 additions & 0 deletions compiler/rustc_type_ir/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ pub enum GoalSource {
ImplWhereBound,
/// Instantiating a higher-ranked goal and re-proving it.
InstantiateHigherRanked,
/// Predicate required for an alias projection to be well-formed.
/// This is used in two places: projecting to an opaque whose hidden type
/// is already registered in the opaque type storage, and for rigid projections.
AliasWellFormed,
}

#[derive_where(Clone; I: Interner, Goal<I, P>: Clone)]
Expand Down
21 changes: 4 additions & 17 deletions tests/ui/associated-types/defaults-unsound-62211-1.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,17 @@ help: consider further restricting `Self`
LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
| +++++++++++++++++++++++++

error[E0271]: type mismatch resolving `<Self as Deref>::Target normalizes-to <Self as Deref>::Target`
--> $DIR/defaults-unsound-62211-1.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ types differ
|
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-1.rs:24:31
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`

error[E0277]: the trait bound `Self: Deref` is not satisfied
--> $DIR/defaults-unsound-62211-1.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ the trait `Deref` is not implemented for `Self`
|
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-1.rs:24:25
--> $DIR/defaults-unsound-62211-1.rs:24:31
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
help: consider further restricting `Self`
|
LL | trait UncheckedCopy: Sized + Deref {
Expand All @@ -75,7 +63,6 @@ help: consider further restricting `Self`
LL | trait UncheckedCopy: Sized + Copy {
| ++++++

error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0277`.
21 changes: 4 additions & 17 deletions tests/ui/associated-types/defaults-unsound-62211-2.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,17 @@ help: consider further restricting `Self`
LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
| +++++++++++++++++++++++++

error[E0271]: type mismatch resolving `<Self as Deref>::Target normalizes-to <Self as Deref>::Target`
--> $DIR/defaults-unsound-62211-2.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ types differ
|
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-2.rs:24:31
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`

error[E0277]: the trait bound `Self: Deref` is not satisfied
--> $DIR/defaults-unsound-62211-2.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ the trait `Deref` is not implemented for `Self`
|
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-2.rs:24:25
--> $DIR/defaults-unsound-62211-2.rs:24:31
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
| ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
help: consider further restricting `Self`
|
LL | trait UncheckedCopy: Sized + Deref {
Expand All @@ -75,7 +63,6 @@ help: consider further restricting `Self`
LL | trait UncheckedCopy: Sized + Copy {
| ++++++

error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0277`.
21 changes: 4 additions & 17 deletions tests/ui/associated-types/issue-54108.next.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
error[E0271]: type mismatch resolving `<<T as SubEncoder>::ActualSize as Add>::Output normalizes-to <<T as SubEncoder>::ActualSize as Add>::Output`
--> $DIR/issue-54108.rs:23:17
|
LL | type Size = <Self as SubEncoder>::ActualSize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
|
note: required by a bound in `Encoder::Size`
--> $DIR/issue-54108.rs:8:20
|
LL | type Size: Add<Output = Self::Size>;
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`

error[E0277]: cannot add `<T as SubEncoder>::ActualSize` to `<T as SubEncoder>::ActualSize`
--> $DIR/issue-54108.rs:23:17
|
Expand All @@ -18,16 +6,15 @@ LL | type Size = <Self as SubEncoder>::ActualSize;
|
= help: the trait `Add` is not implemented for `<T as SubEncoder>::ActualSize`
note: required by a bound in `Encoder::Size`
--> $DIR/issue-54108.rs:8:16
--> $DIR/issue-54108.rs:8:20
|
LL | type Size: Add<Output = Self::Size>;
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
help: consider further restricting the associated type
|
LL | T: SubEncoder, <T as SubEncoder>::ActualSize: Add
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0277`.
7 changes: 1 addition & 6 deletions tests/ui/for/issue-20605.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@

fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
for item in *things { *item = 0 }
//[current]~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
//[next]~^^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
//[next]~| ERROR type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced

// FIXME(-Znext-solver): these error messages are horrible and have to be
// improved before we stabilize the new solver.
//~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0283]: type annotations needed
--> $DIR/ambig-hr-projection-issue-93340.rs:16:5
--> $DIR/ambig-hr-projection-issue-93340.rs:17:5
|
LL | cmp_eq
| ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`
Expand All @@ -15,14 +15,16 @@ help: consider specifying the generic arguments
LL | cmp_eq::<A, B, O>
| +++++++++++

error[E0271]: type mismatch resolving `build_expression<A, B, O>::{opaque#0} normalizes-to _`
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>}`
--> $DIR/ambig-hr-projection-issue-93340.rs:14:1
|
LL | / fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
LL | | ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
| |_________________________________________________^ types differ
| |_________________________________________________^ 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>}`
|
= 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>}`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0271, E0283.
For more information about an error, try `rustc --explain E0271`.
Some errors have detailed explanations: E0277, E0283.
For more information about an error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0283]: type annotations needed
--> $DIR/ambig-hr-projection-issue-93340.rs:16:5
--> $DIR/ambig-hr-projection-issue-93340.rs:17:5
|
LL | cmp_eq
| ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefT

fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
//[next]~^^ expected a `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure
cmp_eq
//~^ ERROR type annotations needed
}
Expand Down
4 changes: 3 additions & 1 deletion tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ struct W<T>(T);
// `usize: Foo` doesn't hold. Therefore we ICE, because we don't expect to still
// encounter weak types in `assemble_alias_bound_candidates_recur`.
fn hello(_: W<A<usize>>) {}
//~^ ERROR the size for values of type `A<usize>` cannot be known at compilation time
//~^ ERROR the trait bound `usize: Foo` is not satisfied
//~| ERROR the trait bound `usize: Foo` is not satisfied
//~| ERROR the trait bound `usize: Foo` is not satisfied

fn main() {}
38 changes: 24 additions & 14 deletions tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,42 @@ LL | #![feature(lazy_type_alias)]
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
error[E0277]: the trait bound `usize: Foo` is not satisfied
--> $DIR/alias-bounds-when-not-wf.rs:16:13
|
LL | fn hello(_: W<A<usize>>) {}
| ^^^^^^^^^^^ types differ

error[E0271]: type mismatch resolving `A<usize> normalizes-to _`
--> $DIR/alias-bounds-when-not-wf.rs:16:10
| ^^^^^^^^^^^ the trait `Foo` is not implemented for `usize`
|
LL | fn hello(_: W<A<usize>>) {}
| ^ types differ
help: this trait has no implementations, consider adding one
--> $DIR/alias-bounds-when-not-wf.rs:6:1
|
LL | trait Foo {}
| ^^^^^^^^^

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

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

error: aborting due to 4 previous errors; 1 warning emitted
error: aborting due to 3 previous errors; 1 warning emitted

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

0 comments on commit c914388

Please sign in to comment.