Skip to content

Commit ab92d92

Browse files
Report better WF obligation leaf obligations in new solver
1 parent 97bf25c commit ab92d92

16 files changed

+119
-92
lines changed

compiler/rustc_trait_selection/src/solve/fulfill.rs

+57-19
Original file line numberDiff line numberDiff line change
@@ -384,39 +384,65 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
384384
return ControlFlow::Break(self.obligation.clone());
385385
}
386386

387+
let tcx = goal.infcx().tcx;
387388
// FIXME: Could we extract a trait ref from a projection here too?
388389
// FIXME: Also, what about considering >1 layer up the stack? May be necessary
389390
// for normalizes-to.
390-
let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else {
391-
return ControlFlow::Break(self.obligation.clone());
391+
let pred_kind = goal.goal().predicate.kind();
392+
let child_mode = match pred_kind.skip_binder() {
393+
ty::PredicateKind::Clause(ty::ClauseKind::Trait(parent_trait_pred)) => {
394+
ChildMode::Trait(pred_kind.rebind(parent_trait_pred))
395+
}
396+
ty::PredicateKind::NormalizesTo(normalizes_to)
397+
if matches!(
398+
normalizes_to.alias.kind(tcx),
399+
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst
400+
) =>
401+
{
402+
ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate {
403+
trait_ref: normalizes_to.alias.trait_ref(tcx),
404+
polarity: ty::PredicatePolarity::Positive,
405+
}))
406+
}
407+
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => {
408+
ChildMode::WellFormedObligation
409+
}
410+
_ => {
411+
return ControlFlow::Break(self.obligation.clone());
412+
}
392413
};
393414

394-
let tcx = goal.infcx().tcx;
395415
let mut impl_where_bound_count = 0;
396416
for nested_goal in candidate.instantiate_nested_goals(self.span()) {
417+
let make_obligation = |cause| Obligation {
418+
cause,
419+
param_env: nested_goal.goal().param_env,
420+
predicate: nested_goal.goal().predicate,
421+
recursion_depth: self.obligation.recursion_depth + 1,
422+
};
423+
397424
let obligation;
398-
match nested_goal.source() {
399-
GoalSource::Misc => {
425+
match (child_mode, nested_goal.source()) {
426+
(ChildMode::Trait(_), GoalSource::Misc) => {
400427
continue;
401428
}
402-
GoalSource::ImplWhereBound => {
403-
obligation = Obligation {
404-
cause: derive_cause(
405-
tcx,
406-
candidate.kind(),
407-
self.obligation.cause.clone(),
408-
impl_where_bound_count,
409-
parent_trait_pred,
410-
),
411-
param_env: nested_goal.goal().param_env,
412-
predicate: nested_goal.goal().predicate,
413-
recursion_depth: self.obligation.recursion_depth + 1,
414-
};
429+
(ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
430+
obligation = make_obligation(derive_cause(
431+
tcx,
432+
candidate.kind(),
433+
self.obligation.cause.clone(),
434+
impl_where_bound_count,
435+
parent_trait_pred,
436+
));
415437
impl_where_bound_count += 1;
416438
}
417-
GoalSource::InstantiateHigherRanked => {
439+
// Skip over a higher-ranked predicate.
440+
(_, GoalSource::InstantiateHigherRanked) => {
418441
obligation = self.obligation.clone();
419442
}
443+
(ChildMode::WellFormedObligation, _) => {
444+
obligation = make_obligation(self.obligation.cause.clone());
445+
}
420446
}
421447

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

465+
#[derive(Copy, Clone)]
466+
enum ChildMode<'tcx> {
467+
// Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
468+
// and skip all `GoalSource::Misc`, which represent useless obligations
469+
// such as alias-eq which may not hold.
470+
Trait(ty::PolyTraitPredicate<'tcx>),
471+
// Skip trying to derive an `ObligationCause` from this obligation, and
472+
// report *all* sub-obligations as if they came directly from the parent
473+
// obligation.
474+
WellFormedObligation,
475+
}
476+
439477
fn derive_cause<'tcx>(
440478
tcx: TyCtxt<'tcx>,
441479
candidate_kind: ProbeKind<'tcx>,
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
error: the type `Foo::Bar<Vec<[u32]>>` is not well-formed
2-
--> $DIR/wf-check-skipped.rs:17:14
1+
error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
2+
--> $DIR/wf-check-skipped.rs:17:25
33
|
44
LL | fn main() -> Foo::Bar::<Vec<[u32]>> {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `Sized` is not implemented for `[u32]`
68

79
error: aborting due to 1 previous error
810

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

tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ impl Foo {
1515
}
1616

1717
fn main() -> Foo::Bar::<Vec<[u32]>> {}
18-
//[next]~^ ERROR the type `Foo::Bar<Vec<[u32]>>` is not well-formed
18+
//[next]~^ ERROR the size for values of type `[u32]` cannot be known at compilation time

tests/ui/for/issue-20605.next.stderr

+1-19
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,13 @@ help: consider mutably borrowing here
1111
LL | for item in &mut *things { *item = 0 }
1212
| ++++
1313

14-
error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
15-
--> $DIR/issue-20605.rs:6:17
16-
|
17-
LL | for item in *things { *item = 0 }
18-
| ^^^^^^^
19-
20-
error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
21-
--> $DIR/issue-20605.rs:6:17
22-
|
23-
LL | for item in *things { *item = 0 }
24-
| ^^^^^^^
25-
26-
error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
27-
--> $DIR/issue-20605.rs:6:17
28-
|
29-
LL | for item in *things { *item = 0 }
30-
| ^^^^^^^
31-
3214
error[E0614]: type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
3315
--> $DIR/issue-20605.rs:6:27
3416
|
3517
LL | for item in *things { *item = 0 }
3618
| ^^^^^
3719

38-
error: aborting due to 5 previous errors
20+
error: aborting due to 2 previous errors
3921

4022
Some errors have detailed explanations: E0277, E0614.
4123
For more information about an error, try `rustc --explain E0277`.

tests/ui/for/issue-20605.rs

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
66
for item in *things { *item = 0 }
77
//[current]~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
88
//[next]~^^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
9-
//[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
10-
//[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
11-
//[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
129
//[next]~| ERROR type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
1310

1411
// FIXME(-Znext-solver): these error messages are horrible and have to be

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ 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 type `W<A<usize>>` is not well-formed
17+
//~^ ERROR the size for values of type `A<usize>` cannot be known at compilation time
1818

1919
fn main() {}

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

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

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

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

tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0282]: type annotations needed
1+
error[E0284]: type annotations needed: cannot satisfy `the constant `{ || {} }` can be evaluated`
22
--> $DIR/const-region-infer-to-static-in-binder.rs:4:10
33
|
44
LL | struct X<const FN: fn() = { || {} }>;
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `{ || {} }`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `{ || {} }` can be evaluated`
66

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

2424
error: aborting due to 3 previous errors
2525

26-
For more information about this error, try `rustc --explain E0282`.
26+
For more information about this error, try `rustc --explain E0284`.

tests/ui/traits/next-solver/issue-118950-root-region.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ trait ToUnit<'a> {
1212
trait Overlap<T> {}
1313

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

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

tests/ui/traits/next-solver/issue-118950-root-region.stderr

+9-3
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,17 @@ LL | #![feature(lazy_type_alias)]
1313
= note: see issue #112792 <https://github.com./rust-lang/rust/issues/112792> for more information
1414
= note: `#[warn(incomplete_features)]` on by default
1515

16-
error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed
16+
error[E0277]: the trait bound `*const T: ToUnit<'a>` is not satisfied
1717
--> $DIR/issue-118950-root-region.rs:14:21
1818
|
1919
LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ToUnit<'a>` is not implemented for `*const T`
21+
|
22+
help: this trait has no implementations, consider adding one
23+
--> $DIR/issue-118950-root-region.rs:8:1
24+
|
25+
LL | trait ToUnit<'a> {
26+
| ^^^^^^^^^^^^^^^^
2127

2228
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) }
2329
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) }
@@ -34,5 +40,5 @@ LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {
3440

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

37-
Some errors have detailed explanations: E0119, E0412.
43+
Some errors have detailed explanations: E0119, E0277, E0412.
3844
For more information about an error, try `rustc --explain E0119`.

tests/ui/traits/next-solver/member-constraints-in-root-universe.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
//@ compile-flags: -Znext-solver
2+
//@ check-pass
23

34
trait Trait {
45
type Ty;
56
}
67

7-
impl Trait for for<'a> fn(&'a u8, &'a u8) {
8+
impl Trait for for<'a, 'b> fn(&'a u8, &'b u8) {
89
type Ty = ();
910
}
1011

1112
// argument is necessary to create universes before registering the hidden type.
1213
fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized {
13-
//~^ ERROR the type `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty` is not well-formed
1414
"hidden type is `&'?0 str` with '?0 member of ['static,]"
1515
}
1616

tests/ui/traits/next-solver/member-constraints-in-root-universe.stderr

-8
This file was deleted.

tests/ui/traits/next-solver/object-unsafety.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
1010

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

1817
// FIXME(-Znext-solver): These error messages are horrible and some of them

tests/ui/traits/next-solver/object-unsafety.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,6 @@ help: consider restricting type parameter `T`
1515
LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
1616
| +++++++++++++++++++
1717

18-
error: the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
19-
--> $DIR/object-unsafety.rs:12:31
20-
|
21-
LL | copy::<dyn Setup<From=T>>(t)
22-
| ^
23-
2418
error[E0308]: mismatched types
2519
--> $DIR/object-unsafety.rs:12:31
2620
|
@@ -37,13 +31,19 @@ note: function defined here
3731
LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
3832
| ^^^^ --------------
3933

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

46-
error: aborting due to 4 previous errors
46+
error: aborting due to 3 previous errors
4747

4848
Some errors have detailed explanations: E0277, E0308.
4949
For more information about an error, try `rustc --explain E0277`.
+19-12
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,37 @@
1-
error: the type `<[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize` is not well-formed
2-
--> $DIR/wf-normalization-sized.rs:19:10
1+
error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
2+
--> $DIR/wf-normalization-sized.rs:19:11
33
|
44
LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `Sized` is not implemented for `[[[[[u8]]]]]`
68

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

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

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

2935
error: aborting due to 4 previous errors
3036

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

tests/ui/wf/wf-normalization-sized.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ impl<T: ?Sized> WellUnformed for T {
1717
}
1818

1919
const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
20-
//[next]~^ the type
21-
//[next]~| the type
20+
//[next]~^ the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
21+
//[next]~| the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
2222
const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
23-
//[next]~^ the type
24-
//[next]~| the type
23+
//[next]~^ the size for values of type `str` cannot be known at compilation time
24+
//[next]~| the size for values of type `str` cannot be known at compilation time
2525

2626
fn main() {}

0 commit comments

Comments
 (0)