Skip to content

Commit

Permalink
Report better WF obligation leaf obligations in new solver
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed May 17, 2024
1 parent 97bf25c commit 119c7bb
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 108 deletions.
77 changes: 57 additions & 20 deletions compiler/rustc_trait_selection/src/solve/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,39 +384,64 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
return ControlFlow::Break(self.obligation.clone());
}

// FIXME: Could we extract a trait ref from a projection here too?
let tcx = goal.infcx().tcx;
// FIXME: Also, what about considering >1 layer up the stack? May be necessary
// for normalizes-to.
let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else {
return ControlFlow::Break(self.obligation.clone());
let pred_kind = goal.goal().predicate.kind();
let child_mode = match pred_kind.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(parent_trait_pred)) => {
ChildMode::Trait(pred_kind.rebind(parent_trait_pred))
}
ty::PredicateKind::NormalizesTo(normalizes_to)
if matches!(
normalizes_to.alias.kind(tcx),
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst
) =>
{
ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate {
trait_ref: normalizes_to.alias.trait_ref(tcx),
polarity: ty::PredicatePolarity::Positive,
}))
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => {
ChildMode::WellFormedObligation
}
_ => {
return ControlFlow::Break(self.obligation.clone());
}
};

let tcx = goal.infcx().tcx;
let mut impl_where_bound_count = 0;
for nested_goal in candidate.instantiate_nested_goals(self.span()) {
let make_obligation = |cause| Obligation {
cause,
param_env: nested_goal.goal().param_env,
predicate: nested_goal.goal().predicate,
recursion_depth: self.obligation.recursion_depth + 1,
};

let obligation;
match nested_goal.source() {
GoalSource::Misc => {
match (child_mode, nested_goal.source()) {
(ChildMode::Trait(_), GoalSource::Misc) => {
continue;
}
GoalSource::ImplWhereBound => {
obligation = Obligation {
cause: derive_cause(
tcx,
candidate.kind(),
self.obligation.cause.clone(),
impl_where_bound_count,
parent_trait_pred,
),
param_env: nested_goal.goal().param_env,
predicate: nested_goal.goal().predicate,
recursion_depth: self.obligation.recursion_depth + 1,
};
(ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
obligation = make_obligation(derive_cause(
tcx,
candidate.kind(),
self.obligation.cause.clone(),
impl_where_bound_count,
parent_trait_pred,
));
impl_where_bound_count += 1;
}
GoalSource::InstantiateHigherRanked => {
// Skip over a higher-ranked predicate.
(_, GoalSource::InstantiateHigherRanked) => {
obligation = self.obligation.clone();
}
(ChildMode::WellFormedObligation, _) => {
obligation = make_obligation(self.obligation.cause.clone());
}
}

// Skip nested goals that aren't the *reason* for our goal's failure.
Expand All @@ -436,6 +461,18 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
}
}

#[derive(Copy, Clone)]
enum ChildMode<'tcx> {
// Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
// and skip all `GoalSource::Misc`, which represent useless obligations
// such as alias-eq which may not hold.
Trait(ty::PolyTraitPredicate<'tcx>),
// Skip trying to derive an `ObligationCause` from this obligation, and
// report *all* sub-obligations as if they came directly from the parent
// obligation.
WellFormedObligation,
}

fn derive_cause<'tcx>(
tcx: TyCtxt<'tcx>,
candidate_kind: ProbeKind<'tcx>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
error: the type `Foo::Bar<Vec<[u32]>>` is not well-formed
--> $DIR/wf-check-skipped.rs:17:14
error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
--> $DIR/wf-check-skipped.rs:17:25
|
LL | fn main() -> Foo::Bar::<Vec<[u32]>> {}
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u32]`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ impl Foo {
}

fn main() -> Foo::Bar::<Vec<[u32]>> {}
//[next]~^ ERROR the type `Foo::Bar<Vec<[u32]>>` is not well-formed
//[next]~^ ERROR the size for values of type `[u32]` cannot be known at compilation time
20 changes: 1 addition & 19 deletions tests/ui/for/issue-20605.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,13 @@ help: consider mutably borrowing here
LL | for item in &mut *things { *item = 0 }
| ++++

error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
--> $DIR/issue-20605.rs:6:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^

error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
--> $DIR/issue-20605.rs:6:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^

error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
--> $DIR/issue-20605.rs:6:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^

error[E0614]: type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
--> $DIR/issue-20605.rs:6:27
|
LL | for item in *things { *item = 0 }
| ^^^^^

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

Some errors have detailed explanations: E0277, E0614.
For more information about an error, try `rustc --explain E0277`.
3 changes: 0 additions & 3 deletions tests/ui/for/issue-20605.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ 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 the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
//[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
//[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
//[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
Expand Down
2 changes: 1 addition & 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,6 @@ 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 type `W<A<usize>>` is not well-formed
//~^ ERROR the size for values of type `A<usize>` cannot be known at compilation time

fn main() {}
7 changes: 5 additions & 2 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,11 +7,14 @@ 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: the type `W<A<usize>>` is not well-formed
error[E0277]: the size for values of type `A<usize>` cannot be known at compilation time
--> $DIR/alias-bounds-when-not-wf.rs:16:13
|
LL | fn hello(_: W<A<usize>>) {}
| ^^^^^^^^^^^
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `A<usize>`

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0282]: type annotations needed
error[E0284]: type annotations needed: cannot satisfy `the constant `{ || {} }` can be evaluated`
--> $DIR/const-region-infer-to-static-in-binder.rs:4:10
|
LL | struct X<const FN: fn() = { || {} }>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `{ || {} }`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `{ || {} }` can be evaluated`

error: using function pointers as const generic parameters is forbidden
--> $DIR/const-region-infer-to-static-in-binder.rs:4:20
Expand All @@ -23,4 +23,4 @@ LL | struct X<const FN: fn() = { || {} }>;

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0284`.
2 changes: 1 addition & 1 deletion tests/ui/traits/next-solver/issue-118950-root-region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait ToUnit<'a> {
trait Overlap<T> {}

type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
//~^ ERROR: not well-formed
//~^ ERROR the trait bound `*const T: ToUnit<'a>` is not satisfied

impl<T> Overlap<T> for T {}

Expand Down
12 changes: 9 additions & 3 deletions tests/ui/traits/next-solver/issue-118950-root-region.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ 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: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed
error[E0277]: the trait bound `*const T: ToUnit<'a>` is not satisfied
--> $DIR/issue-118950-root-region.rs:14:21
|
LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ToUnit<'a>` is not implemented for `*const T`
|
help: this trait has no implementations, consider adding one
--> $DIR/issue-118950-root-region.rs:8:1
|
LL | trait ToUnit<'a> {
| ^^^^^^^^^^^^^^^^

WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }
Expand All @@ -34,5 +40,5 @@ LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {

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

Some errors have detailed explanations: E0119, E0412.
Some errors have detailed explanations: E0119, E0277, E0412.
For more information about an error, try `rustc --explain E0119`.
17 changes: 0 additions & 17 deletions tests/ui/traits/next-solver/member-constraints-in-root-universe.rs

This file was deleted.

This file was deleted.

3 changes: 1 addition & 2 deletions tests/ui/traits/next-solver/object-unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {

pub fn copy_any<T>(t: &T) -> T {
copy::<dyn Setup<From=T>>(t)
//~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
//~^ ERROR the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>`
//~| ERROR mismatched types
//~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
//~| ERROR the trait bound `T: Copy` is not satisfied

// FIXME(-Znext-solver): These error messages are horrible and some of them
Expand Down
18 changes: 9 additions & 9 deletions tests/ui/traits/next-solver/object-unsafety.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ help: consider restricting type parameter `T`
LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
| +++++++++++++++++++

error: the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
--> $DIR/object-unsafety.rs:12:31
|
LL | copy::<dyn Setup<From=T>>(t)
| ^

error[E0308]: mismatched types
--> $DIR/object-unsafety.rs:12:31
|
Expand All @@ -37,13 +31,19 @@ note: function defined here
LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
| ^^^^ --------------

error: the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>`
--> $DIR/object-unsafety.rs:12:5
|
LL | copy::<dyn Setup<From=T>>(t)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup<From = T>: Setup`
|
= note: required because it appears within the type `dyn Setup<From = T>`
help: consider restricting type parameter `T`
|
LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
| +++++++++++++++++++

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

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
31 changes: 19 additions & 12 deletions tests/ui/wf/wf-normalization-sized.next.stderr
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
error: the type `<[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize` is not well-formed
--> $DIR/wf-normalization-sized.rs:19:10
error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
--> $DIR/wf-normalization-sized.rs:19:11
|
LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[[[[[u8]]]]]`

error: the type `<[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize` is not well-formed
--> $DIR/wf-normalization-sized.rs:19:10
error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
--> $DIR/wf-normalization-sized.rs:19:11
|
LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[[[[[u8]]]]]`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: the type `<Vec<str> as WellUnformed>::RequestNormalize` is not well-formed
--> $DIR/wf-normalization-sized.rs:22:10
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/wf-normalization-sized.rs:22:11
|
LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`

error: the type `<Vec<str> as WellUnformed>::RequestNormalize` is not well-formed
--> $DIR/wf-normalization-sized.rs:22:10
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/wf-normalization-sized.rs:22:11
|
LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0277`.
8 changes: 4 additions & 4 deletions tests/ui/wf/wf-normalization-sized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ impl<T: ?Sized> WellUnformed for T {
}

const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
//[next]~^ the type
//[next]~| the type
//[next]~^ the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
//[next]~| the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
//[next]~^ the type
//[next]~| the type
//[next]~^ the size for values of type `str` cannot be known at compilation time
//[next]~| the size for values of type `str` cannot be known at compilation time

fn main() {}

0 comments on commit 119c7bb

Please sign in to comment.