Skip to content

Commit

Permalink
Auto merge of #122317 - compiler-errors:fulfill-method-probe, r=<try>
Browse files Browse the repository at this point in the history
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.

Putting this up for vibe-check mostly. Tests aren't yet blessed, and there are some nuances about whether it's worthwhile to restore regressed diagnostics.

r? lcnr
  • Loading branch information
bors committed Mar 11, 2024
2 parents d255c6a + 3702ab1 commit 1f75533
Show file tree
Hide file tree
Showing 22 changed files with 252 additions and 460 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
[candidate] => format!(
"the method of the same name on {} `{}`",
match candidate.kind {
probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
probe::CandidateKind::InherentImplCandidate(_) => "the inherent impl for",
_ => "trait",
},
self.tcx.def_path_str(candidate.item.container_id(self.tcx))
Expand Down
476 changes: 131 additions & 345 deletions compiler/rustc_hir_typeck/src/method/probe.rs

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions compiler/rustc_trait_selection/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,19 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}

pub fn eq_no_opaques<T: ToTrace<'tcx>>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
expected: T,
actual: T,
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.eq(DefineOpaqueTypes::No, expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}

/// Checks whether `expected` is a subtype of `actual`: `expected <: actual`.
pub fn sub<T: ToTrace<'tcx>>(
&self,
Expand Down
27 changes: 4 additions & 23 deletions tests/ui/derives/issue-91550.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its tr
--> $DIR/issue-91550.rs:8:8
|
LL | struct Value(u32);
| ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq`
| ------------ doesn't satisfy `Value: Eq` or `Value: Hash`
...
LL | hs.insert(Value(0));
| ^^^^^^
|
= note: the following trait bounds were not satisfied:
`Value: Eq`
`Value: PartialEq`
which is required by `Value: Eq`
`Value: Hash`
help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
|
Expand All @@ -22,7 +20,7 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its
--> $DIR/issue-91550.rs:26:9
|
LL | pub struct NoDerives;
| -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq`
| -------------------- doesn't satisfy `NoDerives: Eq`
LL |
LL | struct Object<T>(T);
| ---------------- method `use_eq` not found for this struct
Expand All @@ -37,9 +35,6 @@ LL | impl<T: Eq> Object<T> {
| ^^ ---------
| |
| unsatisfied trait bound introduced here
= note: the following trait bounds were not satisfied:
`NoDerives: PartialEq`
which is required by `NoDerives: Eq`
help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
|
LL + #[derive(Eq, PartialEq)]
Expand All @@ -50,7 +45,7 @@ error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but it
--> $DIR/issue-91550.rs:27:9
|
LL | pub struct NoDerives;
| -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
| -------------------- doesn't satisfy `NoDerives: Ord`
LL |
LL | struct Object<T>(T);
| ---------------- method `use_ord` not found for this struct
Expand All @@ -65,13 +60,6 @@ LL | impl<T: Ord> Object<T> {
| ^^^ ---------
| |
| unsatisfied trait bound introduced here
= note: the following trait bounds were not satisfied:
`NoDerives: PartialOrd`
which is required by `NoDerives: Ord`
`NoDerives: PartialEq`
which is required by `NoDerives: Ord`
`NoDerives: Eq`
which is required by `NoDerives: Ord`
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
|
LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]
Expand All @@ -82,7 +70,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoD
--> $DIR/issue-91550.rs:28:9
|
LL | pub struct NoDerives;
| -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
| -------------------- doesn't satisfy `NoDerives: Ord` or `NoDerives: PartialOrd`
LL |
LL | struct Object<T>(T);
| ---------------- method `use_ord_and_partial_ord` not found for this struct
Expand All @@ -100,13 +88,6 @@ LL | impl<T: Ord + PartialOrd> Object<T> {
| | |
| | unsatisfied trait bound introduced here
| unsatisfied trait bound introduced here
= note: the following trait bounds were not satisfied:
`NoDerives: PartialEq`
which is required by `NoDerives: Ord`
`NoDerives: Eq`
which is required by `NoDerives: Ord`
`NoDerives: PartialEq`
which is required by `NoDerives: PartialOrd`
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
|
LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,15 @@ help: consider relaxing the implicit `Sized` restriction
LL | type Pointer<T>: Deref<Target = T> + ?Sized;
| ++++++++

error[E0599]: the size for values of type `Node<i32, RcFamily>` cannot be known at compilation time
error[E0599]: the variant or associated item `new` exists for enum `Node<i32, RcFamily>`, but its trait bounds were not satisfied
--> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:31:35
|
LL | enum Node<T, P: PointerFamily> {
| ------------------------------ variant or associated item `new` not found for this enum because it doesn't satisfy `Node<i32, RcFamily>: Sized`
| ------------------------------ variant or associated item `new` not found for this enum
...
LL | let mut list = RcNode::<i32>::new();
| ^^^ doesn't have a size known at compile-time
| ^^^ variant or associated item cannot be called on `Node<i32, RcFamily>` due to unsatisfied trait bounds
|
note: trait bound `Node<i32, RcFamily>: Sized` was not satisfied
--> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:18
|
LL | type Pointer<T>: Deref<Target = T>;
| ------- ^ unsatisfied trait bound introduced here
note: trait bound `(dyn Deref<Target = Node<i32, RcFamily>> + 'static): Sized` was not satisfied
--> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:23:29
|
Expand All @@ -37,8 +32,6 @@ LL | impl<T, P: PointerFamily> Node<T, P>
LL | where
LL | P::Pointer<Node<T, P>>: Sized,
| ^^^^^ unsatisfied trait bound introduced here
note: the trait `Sized` must be implemented
--> $SRC_DIR/core/src/marker.rs:LL:COL

error: aborting due to 2 previous errors

Expand Down
6 changes: 2 additions & 4 deletions tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ error[E0599]: the method `filterx` exists for struct `Map<Repeat, {closure@issue
--> $DIR/issue-30786.rs:120:22
|
LL | pub struct Map<S, F> {
| -------------------- method `filterx` not found for this struct because it doesn't satisfy `_: StreamExt`
| -------------------- method `filterx` not found for this struct
...
LL | let filter = map.filterx(|x: &_| true);
| ^^^^^^^ method cannot be called on `Map<Repeat, {closure@issue-30786.rs:119:27}>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`&'a mut &Map<Repeat, {closure@$DIR/issue-30786.rs:119:27: 119:34}>: Stream`
`&'a mut &mut Map<Repeat, {closure@$DIR/issue-30786.rs:119:27: 119:34}>: Stream`
`&'a mut Map<Repeat, {closure@$DIR/issue-30786.rs:119:27: 119:34}>: Stream`
--> $DIR/issue-30786.rs:98:50
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
Expand All @@ -26,15 +25,14 @@ error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64)
--> $DIR/issue-30786.rs:132:24
|
LL | pub struct Filter<S, F> {
| ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt`
| ----------------------- method `countx` not found for this struct
...
LL | let count = filter.countx();
| ^^^^^^ method cannot be called due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream`
`&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream`
`&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream`
--> $DIR/issue-30786.rs:98:50
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
Expand Down
50 changes: 30 additions & 20 deletions tests/ui/impl-trait/issues/issue-62742.stderr
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
--> $DIR/issue-62742.rs:4:5
error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied
--> $DIR/issue-62742.rs:4:16
|
LL | WrongImpl::foo(0i32);
| ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
| ^^^ function or associated item cannot be called on `SafeImpl<_, RawImpl<_>>` due to unsatisfied trait bounds
...
LL | pub struct RawImpl<T>(PhantomData<T>);
| --------------------- doesn't satisfy `RawImpl<_>: Raw<_>`
...
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
| ----------------------------------------- function or associated item `foo` not found for this struct
|
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
note: required by a bound in `SafeImpl::<T, A>::foo`
note: trait bound `RawImpl<_>: Raw<_>` was not satisfied
--> $DIR/issue-62742.rs:29:20
|
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
| ^^^^^^ required by this bound in `SafeImpl::<T, A>::foo`
LL | pub fn foo(value: A::Value) {}
| --- required by a bound in this associated function

error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
--> $DIR/issue-62742.rs:4:5
|
LL | WrongImpl::foo(0i32);
| ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
note: required by a bound in `SafeImpl`
--> $DIR/issue-62742.rs:27:35
| ^^^^^^ --------------
| |
| unsatisfied trait bound introduced here
note: the trait `Raw` must be implemented
--> $DIR/issue-62742.rs:13:1
|
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
| ^^^^^^ required by this bound in `SafeImpl`
LL | pub trait Raw<T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
--> $DIR/issue-62742.rs:7:22
Expand All @@ -51,6 +48,19 @@ note: the trait `Raw` must be implemented
LL | pub trait Raw<T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
--> $DIR/issue-62742.rs:4:5
|
LL | WrongImpl::foo(0i32);
| ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
note: required by a bound in `SafeImpl`
--> $DIR/issue-62742.rs:27:35
|
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
| ^^^^^^ required by this bound in `SafeImpl`

error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
--> $DIR/issue-62742.rs:7:5
|
Expand Down
28 changes: 24 additions & 4 deletions tests/ui/impl-trait/issues/issue-84073.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
error[E0275]: overflow assigning `_` to `Option<_>`
--> $DIR/issue-84073.rs:32:22
error[E0599]: the method `when` exists for struct `RaceBuilder<_, Never<_>>`, but its trait bounds were not satisfied
--> $DIR/issue-84073.rs:32:27
|
LL | pub struct Never<T>(PhantomData<T>);
| ------------------- doesn't satisfy `Never<_>: StatefulFuture<Option<_>>`
...
LL | pub struct RaceBuilder<F, S> {
| ---------------------------- method `when` not found for this struct
...
LL | Race::new(|race| race.when());
| ^^^^
| ^^^^ method cannot be called on `RaceBuilder<_, Never<_>>` due to unsatisfied trait bounds
|
note: trait bound `Never<_>: StatefulFuture<Option<_>>` was not satisfied
--> $DIR/issue-84073.rs:14:8
|
LL | impl<T, F> RaceBuilder<T, F>
| -----------------
LL | where
LL | F: StatefulFuture<Option<T>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the trait `StatefulFuture` must be implemented
--> $DIR/issue-84073.rs:3:1
|
LL | pub trait StatefulFuture<S> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0275`.
For more information about this error, try `rustc --explain E0599`.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ LL | let _result = &Some(42).as_deref();
|
= note: the following trait bounds were not satisfied:
`{integer}: Deref`
which is required by `<{integer} as Deref>::Target = _`

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ LL | let _result = &mut Some(42).as_deref_mut();
|
= note: the following trait bounds were not satisfied:
`{integer}: Deref`
which is required by `<{integer} as Deref>::Target = _`

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ LL | let _result = &Ok(42).as_deref();
|
= note: the following trait bounds were not satisfied:
`{integer}: Deref`
which is required by `<{integer} as Deref>::Target = _`

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ LL | let _result = &mut Ok(42).as_deref_mut();
|
= note: the following trait bounds were not satisfied:
`{integer}: Deref`
which is required by `<{integer} as Deref>::Target = _`

error: aborting due to 1 previous error

Expand Down
6 changes: 2 additions & 4 deletions tests/ui/issues/issue-57362-2.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
--> $DIR/issue-57362-2.rs:22:25
|
LL | let x = <fn (&())>::make_g();
| ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
| ^^^^^^ function or associated item not found in `fn(&())`
|
= note: the following trait bounds were not satisfied:
`for<'a> fn(&'a ()): X`
= help: items from traits can only be used if the trait is implemented and in scope
note: `X` defines an item `make_g`, perhaps you need to implement it
--> $DIR/issue-57362-2.rs:8:1
Expand Down
10 changes: 6 additions & 4 deletions tests/ui/mismatched_types/issue-36053-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, {cl
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
| --------- ^^^^^ method cannot be called due to unsatisfied trait bounds
| |
| doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` or `_: FnMut<(&&str,)>`
| doesn't satisfy `_: FnMut<(&&str,)>` or `_: FnOnce<(&&str,)>`
|
= note: the following trait bounds were not satisfied:
`<{closure@$DIR/issue-36053-2.rs:7:39: 7:48} as FnOnce<(&&str,)>>::Output = bool`
which is required by `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
`{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>`
which is required by `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
`Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
`{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>`
which is required by `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
`{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>`
which is required by `&mut Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
`{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>`
which is required by `&mut Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`

error: aborting due to 2 previous errors
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/missing-trait-bounds/issue-35677.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ LL | this.is_subset(other)
|
= note: the following trait bounds were not satisfied:
`T: Eq`
`T: PartialEq`
which is required by `T: Eq`
`T: Hash`
help: consider restricting the type parameters to satisfy the trait bounds
|
Expand Down
6 changes: 2 additions & 4 deletions tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
--> $DIR/issue-57642-higher-ranked-subtype.rs:31:25
|
LL | let x = <fn (&())>::make_g();
| ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
| ^^^^^^ function or associated item not found in `fn(&())`
|
= note: the following trait bounds were not satisfied:
`for<'a> fn(&'a ()): X`
= help: items from traits can only be used if the trait is implemented and in scope
note: `X` defines an item `make_g`, perhaps you need to implement it
--> $DIR/issue-57642-higher-ranked-subtype.rs:4:1
Expand Down
Loading

0 comments on commit 1f75533

Please sign in to comment.