Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use fulfillment in method probe, not evaluation #122317

Merged
merged 6 commits into from Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Expand Up @@ -889,7 +889,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
518 changes: 174 additions & 344 deletions compiler/rustc_hir_typeck/src/method/probe.rs

Large diffs are not rendered by default.

27 changes: 4 additions & 23 deletions tests/ui/derives/issue-91550.stderr
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
Expand Up @@ -29,5 +29,5 @@ where

fn main() {
let mut list = RcNode::<i32>::new();
//~^ ERROR trait bounds were not satisfied
//~^ ERROR the variant or associated item `new` exists for enum `Node<i32, RcFamily>`, but its trait bounds were not satisfied
}
11 changes: 8 additions & 3 deletions tests/ui/impl-trait/issues/issue-62742.rs
@@ -1,12 +1,17 @@
use std::marker::PhantomData;

fn _alias_check() {
fn a() {
WrongImpl::foo(0i32);
//~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
//~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
//~^ ERROR overflow assigning `_` to `[_]`
}

fn b() {
WrongImpl::<()>::foo(0i32);
//~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
//~| ERROR trait bounds were not satisfied
}

fn c() {
CorrectImpl::foo(0i32);
}

Expand Down
44 changes: 11 additions & 33 deletions tests/ui/impl-trait/issues/issue-62742.stderr
@@ -1,33 +1,11 @@
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
--> $DIR/issue-62742.rs:4:5
error[E0275]: overflow assigning `_` to `[_]`
--> $DIR/issue-62742.rs:4:16
|
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::<T, A>::foo`
--> $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
|
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
| ^^^^^^ required by this bound in `SafeImpl`
| ^^^

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
--> $DIR/issue-62742.rs:9:22
|
LL | WrongImpl::<()>::foo(0i32);
| ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds
Expand All @@ -39,33 +17,33 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
| ----------------------------------------- function or associated item `foo` not found for this struct
|
note: trait bound `RawImpl<()>: Raw<()>` was not satisfied
--> $DIR/issue-62742.rs:29:20
--> $DIR/issue-62742.rs:34:20
|
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
| ^^^^^^ --------------
| |
| unsatisfied trait bound introduced here
note: the trait `Raw` must be implemented
--> $DIR/issue-62742.rs:13:1
--> $DIR/issue-62742.rs:18:1
|
LL | pub trait Raw<T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^

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

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

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0275, E0277, E0599.
For more information about an error, try `rustc --explain E0275`.
3 changes: 2 additions & 1 deletion tests/ui/impl-trait/issues/issue-84073.rs
Expand Up @@ -29,5 +29,6 @@ where
}

fn main() {
Race::new(|race| race.when()); //~ ERROR overflow assigning `_` to `Option<_>`
Race::new(|race| race.when());
//~^ ERROR overflow assigning `_` to `Option<_>`
}
4 changes: 2 additions & 2 deletions tests/ui/impl-trait/issues/issue-84073.stderr
@@ -1,8 +1,8 @@
error[E0275]: overflow assigning `_` to `Option<_>`
--> $DIR/issue-84073.rs:32:22
--> $DIR/issue-84073.rs:32:27
|
LL | Race::new(|race| race.when());
| ^^^^
| ^^^^

error: aborting due to 1 previous error

Expand Down
32 changes: 32 additions & 0 deletions tests/ui/methods/fulfillment-disqualifies-method.rs
@@ -0,0 +1,32 @@
// Tests that using fulfillment in the trait solver means that we detect that a
// method is impossible, leading to no ambiguity.
//@ check-pass
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

#[derive(Default)]
struct W<A, B>(A, B);

trait Constrain {
type Output;
}

impl Constrain for i32 {
type Output = u32;
}

trait Impossible {}

impl<A, B> W<A, B> where A: Constrain<Output = B>, B: Impossible {
fn method(&self) {}
}

impl W<i32, u32> {
fn method(&self) {}
}

fn main() {
let w: W<i32, _> = W::default();
w.method();
}
26 changes: 26 additions & 0 deletions tests/ui/methods/leak-check-disquality.rs
@@ -0,0 +1,26 @@
// Tests that using fulfillment in the trait solver means that we detect that a
// method is impossible, leading to no ambiguity.
//@ check-pass
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

struct W<T, U>(Option<T>, Option<U>);

impl<'a> W<fn(&'a ()), u32> {
fn method(&self) {}
}

trait Leak {}
impl<T: Fn(&())> Leak for T {}

impl<T: Leak> W<T, i32> {
fn method(&self) {}
}

fn test<'a>() {
let x: W<fn(&'a ()), _> = W(None, None);
x.method();
}

fn main() {}
24 changes: 24 additions & 0 deletions tests/ui/methods/self-type-is-sup-no-eq.rs
@@ -0,0 +1,24 @@
//@ check-pass

// Test that we use `sup` not `eq` during method probe, since this has an effect
// on the leak check. This is (conceptually) minimized from a crater run for
// `wrend 0.3.6`.

use std::ops::Deref;

struct A;

impl Deref for A {
type Target = B<dyn Fn(&())>;

fn deref(&self) -> &<Self as Deref>::Target { todo!() }
}

struct B<T: ?Sized>(T);
impl<T> B<dyn Fn(T)> {
fn method(&self) {}
}

fn main() {
A.method();
}
2 changes: 0 additions & 2 deletions tests/ui/missing-trait-bounds/issue-35677.stderr
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
4 changes: 3 additions & 1 deletion tests/ui/nll/issue-57362-2.rs
Expand Up @@ -18,8 +18,10 @@ impl<'a> X for fn(&'a ()) {
}
}

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

fn main() {}
8 changes: 3 additions & 5 deletions tests/ui/nll/issue-57362-2.stderr
@@ -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
--> $DIR/issue-57362-2.rs:22:25
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:23: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
3 changes: 2 additions & 1 deletion tests/ui/nll/issue-57642-higher-ranked-subtype.rs
Expand Up @@ -28,7 +28,8 @@ impl<T> Y for fn(T) {
}

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

fn magical() {
Expand Down
8 changes: 3 additions & 5 deletions tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
@@ -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 All @@ -14,7 +12,7 @@ LL | trait X {
| ^^^^^^^

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