Skip to content

Commit cd90d5c

Browse files
committed
Auto merge of #122317 - compiler-errors:fulfill-method-probe, r=lcnr
Use fulfillment in method probe, not evaluation This PR reworks method probing to use fulfillment instead of a `for`-loop of `evaluate_predicate` calls, and moves normalization from method candidate assembly into the `consider_probe`, where it's applied to *all* candidates. This last part coincidentally fixes #121643 (comment). Regarding *why* this large rewrite is done: In general, it's an anti-pattern to do `for o in obligations { evaluate(o); }` because it's not compatible with the way that the new solver emits alias-relate obligations which constrain variables that may show up in other predicates. r? lcnr
2 parents ad07aa1 + 8995c2c commit cd90d5c

19 files changed

+322
-457
lines changed

compiler/rustc_hir_typeck/src/demand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
889889
[candidate] => format!(
890890
"the method of the same name on {} `{}`",
891891
match candidate.kind {
892-
probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
892+
probe::CandidateKind::InherentImplCandidate(_) => "the inherent impl for",
893893
_ => "trait",
894894
},
895895
self.tcx.def_path_str(candidate.item.container_id(self.tcx))

compiler/rustc_hir_typeck/src/method/probe.rs

+174-344
Large diffs are not rendered by default.

tests/ui/derives/issue-91550.stderr

+4-23
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its tr
22
--> $DIR/issue-91550.rs:8:8
33
|
44
LL | struct Value(u32);
5-
| ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq`
5+
| ------------ doesn't satisfy `Value: Eq` or `Value: Hash`
66
...
77
LL | hs.insert(Value(0));
88
| ^^^^^^
99
|
1010
= note: the following trait bounds were not satisfied:
1111
`Value: Eq`
12-
`Value: PartialEq`
13-
which is required by `Value: Eq`
1412
`Value: Hash`
1513
help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
1614
|
@@ -22,7 +20,7 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its
2220
--> $DIR/issue-91550.rs:26:9
2321
|
2422
LL | pub struct NoDerives;
25-
| -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq`
23+
| -------------------- doesn't satisfy `NoDerives: Eq`
2624
LL |
2725
LL | struct Object<T>(T);
2826
| ---------------- method `use_eq` not found for this struct
@@ -37,9 +35,6 @@ LL | impl<T: Eq> Object<T> {
3735
| ^^ ---------
3836
| |
3937
| unsatisfied trait bound introduced here
40-
= note: the following trait bounds were not satisfied:
41-
`NoDerives: PartialEq`
42-
which is required by `NoDerives: Eq`
4338
help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
4439
|
4540
LL + #[derive(Eq, PartialEq)]
@@ -50,7 +45,7 @@ error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but it
5045
--> $DIR/issue-91550.rs:27:9
5146
|
5247
LL | pub struct NoDerives;
53-
| -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
48+
| -------------------- doesn't satisfy `NoDerives: Ord`
5449
LL |
5550
LL | struct Object<T>(T);
5651
| ---------------- method `use_ord` not found for this struct
@@ -65,13 +60,6 @@ LL | impl<T: Ord> Object<T> {
6560
| ^^^ ---------
6661
| |
6762
| unsatisfied trait bound introduced here
68-
= note: the following trait bounds were not satisfied:
69-
`NoDerives: PartialOrd`
70-
which is required by `NoDerives: Ord`
71-
`NoDerives: PartialEq`
72-
which is required by `NoDerives: Ord`
73-
`NoDerives: Eq`
74-
which is required by `NoDerives: Ord`
7563
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
7664
|
7765
LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]
@@ -82,7 +70,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoD
8270
--> $DIR/issue-91550.rs:28:9
8371
|
8472
LL | pub struct NoDerives;
85-
| -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
73+
| -------------------- doesn't satisfy `NoDerives: Ord` or `NoDerives: PartialOrd`
8674
LL |
8775
LL | struct Object<T>(T);
8876
| ---------------- method `use_ord_and_partial_ord` not found for this struct
@@ -100,13 +88,6 @@ LL | impl<T: Ord + PartialOrd> Object<T> {
10088
| | |
10189
| | unsatisfied trait bound introduced here
10290
| unsatisfied trait bound introduced here
103-
= note: the following trait bounds were not satisfied:
104-
`NoDerives: PartialEq`
105-
which is required by `NoDerives: Ord`
106-
`NoDerives: Eq`
107-
which is required by `NoDerives: Ord`
108-
`NoDerives: PartialEq`
109-
which is required by `NoDerives: PartialOrd`
11091
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
11192
|
11293
LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]

tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ where
2929

3030
fn main() {
3131
let mut list = RcNode::<i32>::new();
32-
//~^ ERROR trait bounds were not satisfied
32+
//~^ ERROR the variant or associated item `new` exists for enum `Node<i32, RcFamily>`, but its trait bounds were not satisfied
3333
}

tests/ui/impl-trait/issues/issue-62742.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
use std::marker::PhantomData;
22

3-
fn _alias_check() {
3+
fn a() {
44
WrongImpl::foo(0i32);
5-
//~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
6-
//~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
5+
//~^ ERROR overflow assigning `_` to `[_]`
6+
}
7+
8+
fn b() {
79
WrongImpl::<()>::foo(0i32);
810
//~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
911
//~| ERROR trait bounds were not satisfied
12+
}
13+
14+
fn c() {
1015
CorrectImpl::foo(0i32);
1116
}
1217

+11-33
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,11 @@
1-
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
2-
--> $DIR/issue-62742.rs:4:5
1+
error[E0275]: overflow assigning `_` to `[_]`
2+
--> $DIR/issue-62742.rs:4:16
33
|
44
LL | WrongImpl::foo(0i32);
5-
| ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
6-
|
7-
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
8-
note: required by a bound in `SafeImpl::<T, A>::foo`
9-
--> $DIR/issue-62742.rs:29:20
10-
|
11-
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
12-
| ^^^^^^ required by this bound in `SafeImpl::<T, A>::foo`
13-
LL | pub fn foo(value: A::Value) {}
14-
| --- required by a bound in this associated function
15-
16-
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
17-
--> $DIR/issue-62742.rs:4:5
18-
|
19-
LL | WrongImpl::foo(0i32);
20-
| ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
21-
|
22-
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
23-
note: required by a bound in `SafeImpl`
24-
--> $DIR/issue-62742.rs:27:35
25-
|
26-
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
27-
| ^^^^^^ required by this bound in `SafeImpl`
5+
| ^^^
286

297
error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
30-
--> $DIR/issue-62742.rs:7:22
8+
--> $DIR/issue-62742.rs:9:22
319
|
3210
LL | WrongImpl::<()>::foo(0i32);
3311
| ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds
@@ -39,33 +17,33 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
3917
| ----------------------------------------- function or associated item `foo` not found for this struct
4018
|
4119
note: trait bound `RawImpl<()>: Raw<()>` was not satisfied
42-
--> $DIR/issue-62742.rs:29:20
20+
--> $DIR/issue-62742.rs:34:20
4321
|
4422
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
4523
| ^^^^^^ --------------
4624
| |
4725
| unsatisfied trait bound introduced here
4826
note: the trait `Raw` must be implemented
49-
--> $DIR/issue-62742.rs:13:1
27+
--> $DIR/issue-62742.rs:18:1
5028
|
5129
LL | pub trait Raw<T: ?Sized> {
5230
| ^^^^^^^^^^^^^^^^^^^^^^^^
5331

5432
error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
55-
--> $DIR/issue-62742.rs:7:5
33+
--> $DIR/issue-62742.rs:9:5
5634
|
5735
LL | WrongImpl::<()>::foo(0i32);
5836
| ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
5937
|
6038
= help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
6139
= help: for that trait implementation, expected `[()]`, found `()`
6240
note: required by a bound in `SafeImpl`
63-
--> $DIR/issue-62742.rs:27:35
41+
--> $DIR/issue-62742.rs:32:35
6442
|
6543
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
6644
| ^^^^^^ required by this bound in `SafeImpl`
6745

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

70-
Some errors have detailed explanations: E0277, E0599.
71-
For more information about an error, try `rustc --explain E0277`.
48+
Some errors have detailed explanations: E0275, E0277, E0599.
49+
For more information about an error, try `rustc --explain E0275`.

tests/ui/impl-trait/issues/issue-84073.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ where
2929
}
3030

3131
fn main() {
32-
Race::new(|race| race.when()); //~ ERROR overflow assigning `_` to `Option<_>`
32+
Race::new(|race| race.when());
33+
//~^ ERROR overflow assigning `_` to `Option<_>`
3334
}

tests/ui/impl-trait/issues/issue-84073.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0275]: overflow assigning `_` to `Option<_>`
2-
--> $DIR/issue-84073.rs:32:22
2+
--> $DIR/issue-84073.rs:32:27
33
|
44
LL | Race::new(|race| race.when());
5-
| ^^^^
5+
| ^^^^
66

77
error: aborting due to 1 previous error
88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Tests that using fulfillment in the trait solver means that we detect that a
2+
// method is impossible, leading to no ambiguity.
3+
//@ check-pass
4+
//@ revisions: current next
5+
//@ ignore-compare-mode-next-solver (explicit revisions)
6+
//@[next] compile-flags: -Znext-solver
7+
8+
#[derive(Default)]
9+
struct W<A, B>(A, B);
10+
11+
trait Constrain {
12+
type Output;
13+
}
14+
15+
impl Constrain for i32 {
16+
type Output = u32;
17+
}
18+
19+
trait Impossible {}
20+
21+
impl<A, B> W<A, B> where A: Constrain<Output = B>, B: Impossible {
22+
fn method(&self) {}
23+
}
24+
25+
impl W<i32, u32> {
26+
fn method(&self) {}
27+
}
28+
29+
fn main() {
30+
let w: W<i32, _> = W::default();
31+
w.method();
32+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Tests that using fulfillment in the trait solver means that we detect that a
2+
// method is impossible, leading to no ambiguity.
3+
//@ check-pass
4+
//@ revisions: current next
5+
//@ ignore-compare-mode-next-solver (explicit revisions)
6+
//@[next] compile-flags: -Znext-solver
7+
8+
struct W<T, U>(Option<T>, Option<U>);
9+
10+
impl<'a> W<fn(&'a ()), u32> {
11+
fn method(&self) {}
12+
}
13+
14+
trait Leak {}
15+
impl<T: Fn(&())> Leak for T {}
16+
17+
impl<T: Leak> W<T, i32> {
18+
fn method(&self) {}
19+
}
20+
21+
fn test<'a>() {
22+
let x: W<fn(&'a ()), _> = W(None, None);
23+
x.method();
24+
}
25+
26+
fn main() {}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//@ check-pass
2+
3+
// Test that we use `sup` not `eq` during method probe, since this has an effect
4+
// on the leak check. This is (conceptually) minimized from a crater run for
5+
// `wrend 0.3.6`.
6+
7+
use std::ops::Deref;
8+
9+
struct A;
10+
11+
impl Deref for A {
12+
type Target = B<dyn Fn(&())>;
13+
14+
fn deref(&self) -> &<Self as Deref>::Target { todo!() }
15+
}
16+
17+
struct B<T: ?Sized>(T);
18+
impl<T> B<dyn Fn(T)> {
19+
fn method(&self) {}
20+
}
21+
22+
fn main() {
23+
A.method();
24+
}

tests/ui/missing-trait-bounds/issue-35677.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ LL | this.is_subset(other)
66
|
77
= note: the following trait bounds were not satisfied:
88
`T: Eq`
9-
`T: PartialEq`
10-
which is required by `T: Eq`
119
`T: Hash`
1210
help: consider restricting the type parameters to satisfy the trait bounds
1311
|

tests/ui/nll/issue-57362-2.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ impl<'a> X for fn(&'a ()) {
1818
}
1919
}
2020

21+
// FIXME(@compiler-errors): This error message is less than helpful.
2122
fn g() {
22-
let x = <fn (&())>::make_g(); //~ ERROR the function
23+
let x = <fn (&())>::make_g();
24+
//~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
2325
}
2426

2527
fn main() {}

tests/ui/nll/issue-57362-2.stderr

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
2-
--> $DIR/issue-57362-2.rs:22:25
1+
error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
2+
--> $DIR/issue-57362-2.rs:23:25
33
|
44
LL | let x = <fn (&())>::make_g();
5-
| ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
5+
| ^^^^^^ function or associated item not found in `fn(&())`
66
|
7-
= note: the following trait bounds were not satisfied:
8-
`for<'a> fn(&'a ()): X`
97
= help: items from traits can only be used if the trait is implemented and in scope
108
note: `X` defines an item `make_g`, perhaps you need to implement it
119
--> $DIR/issue-57362-2.rs:8:1

tests/ui/nll/issue-57642-higher-ranked-subtype.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ impl<T> Y for fn(T) {
2828
}
2929

3030
fn higher_ranked_region_has_lost_its_binder() {
31-
let x = <fn (&())>::make_g(); //~ ERROR the function
31+
let x = <fn (&())>::make_g();
32+
//~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
3233
}
3334

3435
fn magical() {

tests/ui/nll/issue-57642-higher-ranked-subtype.stderr

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
1+
error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
22
--> $DIR/issue-57642-higher-ranked-subtype.rs:31:25
33
|
44
LL | let x = <fn (&())>::make_g();
5-
| ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
5+
| ^^^^^^ function or associated item not found in `fn(&())`
66
|
7-
= note: the following trait bounds were not satisfied:
8-
`for<'a> fn(&'a ()): X`
97
= help: items from traits can only be used if the trait is implemented and in scope
108
note: `X` defines an item `make_g`, perhaps you need to implement it
119
--> $DIR/issue-57642-higher-ranked-subtype.rs:4:1
@@ -14,7 +12,7 @@ LL | trait X {
1412
| ^^^^^^^
1513

1614
error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'a> fn(&'a ())` in the current scope
17-
--> $DIR/issue-57642-higher-ranked-subtype.rs:35:25
15+
--> $DIR/issue-57642-higher-ranked-subtype.rs:36:25
1816
|
1917
LL | let x = <fn (&())>::make_f();
2018
| ^^^^^^ function or associated item not found in `fn(&())`

0 commit comments

Comments
 (0)