From b28221e74f5f05d0f7a6212f99c9d5af868c0ed3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 15 Apr 2024 11:10:50 +0000 Subject: [PATCH 1/3] Use diagnostic method for diagnostics --- compiler/rustc_hir_typeck/src/callee.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 9736c8b89204e..93222c1868651 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; }; - let pick = self.confirm_method( + let pick = self.confirm_method_for_diagnostic( call_expr.span, callee_expr, call_expr, From c75f7283bf52c6e2ec6a178f2b7717a4daddacf4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 15 Apr 2024 11:20:33 +0000 Subject: [PATCH 2/3] Add some tests --- .../call_method_ambiguous.next.stderr | 17 ++++++++ tests/ui/impl-trait/call_method_ambiguous.rs | 39 +++++++++++++++++ .../call_method_on_inherent_impl.next.stderr | 17 ++++++++ .../call_method_on_inherent_impl.rs | 25 +++++++++++ ...inherent_impl_on_rigid_type.current.stderr | 16 +++++++ ...on_inherent_impl_on_rigid_type.next.stderr | 17 ++++++++ ...l_method_on_inherent_impl_on_rigid_type.rs | 22 ++++++++++ ...method_on_inherent_impl_ref.current.stderr | 40 ++++++++++++++++++ ...ll_method_on_inherent_impl_ref.next.stderr | 31 ++++++++++++++ .../call_method_on_inherent_impl_ref.rs | 35 ++++++++++++++++ ...all_method_without_import.no_import.stderr | 37 ++++++++++++++++ .../impl-trait/call_method_without_import.rs | 42 +++++++++++++++++++ .../method-resolution.current.stderr | 36 ++++++++++++++++ tests/ui/impl-trait/method-resolution.rs | 29 +++++++++++++ .../impl-trait/method-resolution2.next.stderr | 20 +++++++++ tests/ui/impl-trait/method-resolution2.rs | 31 ++++++++++++++ .../method-resolution3.current.stderr | 37 ++++++++++++++++ .../impl-trait/method-resolution3.next.stderr | 20 +++++++++ tests/ui/impl-trait/method-resolution3.rs | 29 +++++++++++++ .../impl-trait/method-resolution4.next.stderr | 22 ++++++++++ tests/ui/impl-trait/method-resolution4.rs | 20 +++++++++ .../recursive-parent-trait-method-call.rs | 42 +++++++++++++++++++ .../method_resolution.current.stderr | 15 +++++++ .../method_resolution.next.stderr | 12 ++++++ .../method_resolution.rs | 30 +++++++++++++ .../method_resolution2.current.stderr | 36 ++++++++++++++++ .../method_resolution2.rs | 30 +++++++++++++ .../method_resolution3.current.stderr | 21 ++++++++++ .../method_resolution3.next.stderr | 15 +++++++ .../method_resolution3.rs | 36 ++++++++++++++++ .../method_resolution4.current.stderr | 21 ++++++++++ .../method_resolution4.next.stderr | 15 +++++++ .../method_resolution4.rs | 39 +++++++++++++++++ .../method_resolution5.current.stderr | 15 +++++++ .../method_resolution5.rs | 34 +++++++++++++++ ...on_trait_method_from_opaque.current.stderr | 15 +++++++ ...ution_trait_method_from_opaque.next.stderr | 9 ++++ ...hod_resolution_trait_method_from_opaque.rs | 31 ++++++++++++++ 38 files changed, 998 insertions(+) create mode 100644 tests/ui/impl-trait/call_method_ambiguous.next.stderr create mode 100644 tests/ui/impl-trait/call_method_ambiguous.rs create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl.rs create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr create mode 100644 tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs create mode 100644 tests/ui/impl-trait/call_method_without_import.no_import.stderr create mode 100644 tests/ui/impl-trait/call_method_without_import.rs create mode 100644 tests/ui/impl-trait/method-resolution.current.stderr create mode 100644 tests/ui/impl-trait/method-resolution.rs create mode 100644 tests/ui/impl-trait/method-resolution2.next.stderr create mode 100644 tests/ui/impl-trait/method-resolution2.rs create mode 100644 tests/ui/impl-trait/method-resolution3.current.stderr create mode 100644 tests/ui/impl-trait/method-resolution3.next.stderr create mode 100644 tests/ui/impl-trait/method-resolution3.rs create mode 100644 tests/ui/impl-trait/method-resolution4.next.stderr create mode 100644 tests/ui/impl-trait/method-resolution4.rs create mode 100644 tests/ui/impl-trait/recursive-parent-trait-method-call.rs create mode 100644 tests/ui/type-alias-impl-trait/method_resolution.current.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution.next.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution.rs create mode 100644 tests/ui/type-alias-impl-trait/method_resolution2.current.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution2.rs create mode 100644 tests/ui/type-alias-impl-trait/method_resolution3.current.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution3.next.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution3.rs create mode 100644 tests/ui/type-alias-impl-trait/method_resolution4.current.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution4.next.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution4.rs create mode 100644 tests/ui/type-alias-impl-trait/method_resolution5.current.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution5.rs create mode 100644 tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr create mode 100644 tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs diff --git a/tests/ui/impl-trait/call_method_ambiguous.next.stderr b/tests/ui/impl-trait/call_method_ambiguous.next.stderr new file mode 100644 index 0000000000000..cd222aa7ae9fc --- /dev/null +++ b/tests/ui/impl-trait/call_method_ambiguous.next.stderr @@ -0,0 +1,17 @@ +error[E0282]: type annotations needed + --> $DIR/call_method_ambiguous.rs:29:13 + | +LL | let mut iter = foo(n - 1, m); + | ^^^^^^^^ +LL | +LL | assert_eq!(iter.get(), 1); + | ---- type must be known at this point + | +help: consider giving `iter` an explicit type + | +LL | let mut iter: /* Type */ = foo(n - 1, m); + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/call_method_ambiguous.rs b/tests/ui/impl-trait/call_method_ambiguous.rs new file mode 100644 index 0000000000000..c26c01e002d85 --- /dev/null +++ b/tests/ui/impl-trait/call_method_ambiguous.rs @@ -0,0 +1,39 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@[current] run-pass + +#![feature(precise_capturing)] +#![allow(incomplete_features)] + +trait Get { + fn get(&mut self) -> u32; +} + +impl Get for () { + fn get(&mut self) -> u32 { + 0 + } +} + +impl Get for &mut T +where + T: Get, +{ + fn get(&mut self) -> u32 { + T::get(self) + 1 + } +} + +fn foo(n: usize, m: &mut ()) -> impl use<'_> Get { + if n > 0 { + let mut iter = foo(n - 1, m); + //[next]~^ type annotations needed + assert_eq!(iter.get(), 1); + } + m +} + +fn main() { + let g = foo(1, &mut ()).get(); + assert_eq!(g, 1); +} diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr new file mode 100644 index 0000000000000..271051f120abc --- /dev/null +++ b/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr @@ -0,0 +1,17 @@ +error[E0282]: type annotations needed + --> $DIR/call_method_on_inherent_impl.rs:18:13 + | +LL | let x = my_foo(); + | ^ +LL | +LL | x.my_debug(); + | - type must be known at this point + | +help: consider giving `x` an explicit type + | +LL | let x: /* Type */ = my_foo(); + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.rs b/tests/ui/impl-trait/call_method_on_inherent_impl.rs new file mode 100644 index 0000000000000..17f7cad660db1 --- /dev/null +++ b/tests/ui/impl-trait/call_method_on_inherent_impl.rs @@ -0,0 +1,25 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@[current] check-pass + +trait MyDebug { + fn my_debug(&self); +} + +impl MyDebug for T +where + T: std::fmt::Debug, +{ + fn my_debug(&self) {} +} + +fn my_foo() -> impl std::fmt::Debug { + if false { + let x = my_foo(); + //[next]~^ type annotations needed + x.my_debug(); + } + () +} + +fn main() {} diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr new file mode 100644 index 0000000000000..6ecb2b05fc56b --- /dev/null +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr @@ -0,0 +1,16 @@ +error[E0599]: no method named `my_debug` found for reference `&impl Debug` in the current scope + --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:16:11 + | +LL | x.my_debug(); + | ^^^^^^^^ method not found in `&impl Debug` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it + --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:4:1 + | +LL | trait MyDebug { + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr new file mode 100644 index 0000000000000..5fb0b8f1d14b2 --- /dev/null +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr @@ -0,0 +1,17 @@ +error[E0282]: type annotations needed for `&_` + --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:14:13 + | +LL | let x = &my_foo(); + | ^ +LL | +LL | x.my_debug(); + | -------- type must be known at this point + | +help: consider giving `x` an explicit type, where the placeholders `_` are specified + | +LL | let x: &_ = &my_foo(); + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs new file mode 100644 index 0000000000000..7fb2ff3b2bcc6 --- /dev/null +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs @@ -0,0 +1,22 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +trait MyDebug { + fn my_debug(&self); +} + +impl MyDebug for &() { + fn my_debug(&self) {} +} + +fn my_foo() -> impl std::fmt::Debug { + if false { + let x = &my_foo(); + //[next]~^ ERROR: type annotations needed + x.my_debug(); + //[current]~^ ERROR: no method named `my_debug` + } + () +} + +fn main() {} diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr new file mode 100644 index 0000000000000..fe6e166cb4fa1 --- /dev/null +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr @@ -0,0 +1,40 @@ +error[E0599]: no method named `my_debug` found for opaque type `impl Debug` in the current scope + --> $DIR/call_method_on_inherent_impl_ref.rs:20:11 + | +LL | fn my_debug(&self); + | -------- the method is available for `&impl Debug` here +... +LL | x.my_debug(); + | ^^^^^^^^ method not found in `impl Debug` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it + --> $DIR/call_method_on_inherent_impl_ref.rs:4:1 + | +LL | trait MyDebug { + | ^^^^^^^^^^^^^ + +error[E0391]: cycle detected when computing type of opaque `my_foo::{opaque#0}` + --> $DIR/call_method_on_inherent_impl_ref.rs:15:16 + | +LL | fn my_foo() -> impl std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `my_foo`... + --> $DIR/call_method_on_inherent_impl_ref.rs:20:9 + | +LL | x.my_debug(); + | ^ + = note: ...which requires evaluating trait selection obligation `my_foo::{opaque#0}: core::marker::Unpin`... + = note: ...which again requires computing type of opaque `my_foo::{opaque#0}`, completing the cycle +note: cycle used when computing type of `my_foo::{opaque#0}` + --> $DIR/call_method_on_inherent_impl_ref.rs:15:16 + | +LL | fn my_foo() -> impl std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0391, E0599. +For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr new file mode 100644 index 0000000000000..327f6ca3450f1 --- /dev/null +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr @@ -0,0 +1,31 @@ +error[E0282]: type annotations needed + --> $DIR/call_method_on_inherent_impl_ref.rs:18:13 + | +LL | let x = my_foo(); + | ^ +LL | +LL | x.my_debug(); + | - type must be known at this point + | +help: consider giving `x` an explicit type + | +LL | let x: /* Type */ = my_foo(); + | ++++++++++++ + +error[E0282]: type annotations needed for `&_` + --> $DIR/call_method_on_inherent_impl_ref.rs:28:13 + | +LL | let x = &my_bar(); + | ^ +LL | +LL | x.my_debug(); + | -------- type must be known at this point + | +help: consider giving `x` an explicit type, where the placeholders `_` are specified + | +LL | let x: &_ = &my_bar(); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs new file mode 100644 index 0000000000000..40ad21532a4e2 --- /dev/null +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs @@ -0,0 +1,35 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +trait MyDebug { + fn my_debug(&self); +} + +impl MyDebug for &T +where + T: std::fmt::Debug, +{ + fn my_debug(&self) {} +} + +fn my_foo() -> impl std::fmt::Debug { + //[current]~^ cycle + if false { + let x = my_foo(); + //[next]~^ type annotations needed + x.my_debug(); + //[current]~^ no method named `my_debug` found + } + () +} + +fn my_bar() -> impl std::fmt::Debug { + if false { + let x = &my_bar(); + //[next]~^ type annotations needed + x.my_debug(); + } + () +} + +fn main() {} diff --git a/tests/ui/impl-trait/call_method_without_import.no_import.stderr b/tests/ui/impl-trait/call_method_without_import.no_import.stderr new file mode 100644 index 0000000000000..72982b695bbb0 --- /dev/null +++ b/tests/ui/impl-trait/call_method_without_import.no_import.stderr @@ -0,0 +1,37 @@ +error[E0599]: no method named `fmt` found for opaque type `impl Debug` in the current scope + --> $DIR/call_method_without_import.rs:17:11 + | +LL | x.fmt(f); + | ^^^ method not found in `impl Debug` + --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL + | + = note: the method is available for `impl Debug` here + | + = help: items from traits can only be used if the trait is in scope +help: trait `Debug` which provides `fmt` is implemented but not in scope; perhaps you want to import it + | +LL + use std::fmt::Debug; + | + +error[E0599]: no method named `fmt` found for mutable reference `&mut impl Debug` in the current scope + --> $DIR/call_method_without_import.rs:26:11 + | +LL | x.fmt(f); + | ^^^ method not found in `&mut impl Debug` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits which provide `fmt` are implemented but not in scope; perhaps you want to import one of them + | +LL + use std::fmt::Binary; + | +LL + use std::fmt::Debug; + | +LL + use std::fmt::Display; + | +LL + use std::fmt::LowerExp; + | + and 5 other candidates + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/impl-trait/call_method_without_import.rs b/tests/ui/impl-trait/call_method_without_import.rs new file mode 100644 index 0000000000000..d62777ea2835d --- /dev/null +++ b/tests/ui/impl-trait/call_method_without_import.rs @@ -0,0 +1,42 @@ +//! Test that opaque types only pick up methods from traits in their bounds +//! if the trait is imported. +//! +//! FIXME: always look through the bounds of an opaque type to see if there are +//! methods that could be called on any of the bound traits, irrespective of +//! imported traits. + +//@ revisions: import no_import +//@[import] check-pass + +#[cfg(import)] +use std::fmt::Debug as _; + +fn foo(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug { + if false { + let x = foo(f); + x.fmt(f); + //[no_import]~^ ERROR: no method named `fmt` found + } + () +} + +fn foo1(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug { + if false { + let x = &mut foo(f); + x.fmt(f); + //[no_import]~^ ERROR: no method named `fmt` found + } + () +} + +// inconsistent with this +fn bar(t: impl std::fmt::Debug, f: &mut std::fmt::Formatter<'_>) { + t.fmt(f); +} + +// and the desugared version, of course +fn baz(t: T, f: &mut std::fmt::Formatter<'_>) { + t.fmt(f); +} + +fn main() {} diff --git a/tests/ui/impl-trait/method-resolution.current.stderr b/tests/ui/impl-trait/method-resolution.current.stderr new file mode 100644 index 0000000000000..6d10693c8933b --- /dev/null +++ b/tests/ui/impl-trait/method-resolution.current.stderr @@ -0,0 +1,36 @@ +error[E0599]: no method named `bar` found for struct `Bar` in the current scope + --> $DIR/method-resolution.rs:23:11 + | +LL | struct Bar(T); + | ------------- method `bar` not found for this struct +... +LL | x.bar(); + | ^^^ method not found in `Bar` + | + = note: the method was found for + - `Bar` + +error[E0391]: cycle detected when computing type of opaque `foo::{opaque#0}` + --> $DIR/method-resolution.rs:19:24 + | +LL | fn foo(x: bool) -> Bar { + | ^^^^^^^^^^ + | +note: ...which requires type-checking `foo`... + --> $DIR/method-resolution.rs:23:9 + | +LL | x.bar(); + | ^ + = note: ...which requires evaluating trait selection obligation `Bar: core::marker::Unpin`... + = note: ...which again requires computing type of opaque `foo::{opaque#0}`, completing the cycle +note: cycle used when computing type of `foo::{opaque#0}` + --> $DIR/method-resolution.rs:19:24 + | +LL | fn foo(x: bool) -> Bar { + | ^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0391, E0599. +For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/method-resolution.rs b/tests/ui/impl-trait/method-resolution.rs new file mode 100644 index 0000000000000..07618aa64085d --- /dev/null +++ b/tests/ui/impl-trait/method-resolution.rs @@ -0,0 +1,29 @@ +//! Check that we do not constrain hidden types during method resolution. +//! Otherwise we'd pick up that calling `bar` can be satisfied iff `u32` +//! is the hidden type of the RPIT. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +trait Trait {} + +impl Trait for u32 {} + +struct Bar(T); + +impl Bar { + fn bar(self) {} +} + +fn foo(x: bool) -> Bar { + //[current]~^ ERROR: cycle detected + if x { + let x = foo(false); + x.bar(); + //[current]~^ ERROR: no method named `bar` found + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/method-resolution2.next.stderr b/tests/ui/impl-trait/method-resolution2.next.stderr new file mode 100644 index 0000000000000..223430e1658b4 --- /dev/null +++ b/tests/ui/impl-trait/method-resolution2.next.stderr @@ -0,0 +1,20 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/method-resolution2.rs:25:11 + | +LL | x.bar(); + | ^^^ multiple `bar` found + | +note: candidate #1 is defined in an impl for the type `Bar` + --> $DIR/method-resolution2.rs:19:5 + | +LL | fn bar(self) {} + | ^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Bar` + --> $DIR/method-resolution2.rs:15:5 + | +LL | fn bar(self) {} + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/impl-trait/method-resolution2.rs b/tests/ui/impl-trait/method-resolution2.rs new file mode 100644 index 0000000000000..2930b42b8bca0 --- /dev/null +++ b/tests/ui/impl-trait/method-resolution2.rs @@ -0,0 +1,31 @@ +//! Check that the method call does not constrain the RPIT to `i32`, even though +//! `i32` is the only trait that satisfies the RPIT's trait bounds. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@[current] check-pass + +trait Trait {} + +impl Trait for i32 {} + +struct Bar(T); + +impl Bar { + fn bar(self) {} +} + +impl Bar { + fn bar(self) {} +} + +fn foo(x: bool) -> Bar { + if x { + let x = foo(false); + x.bar(); + //[next]~^ ERROR: multiple applicable items in scope + } + Bar(42_i32) +} + +fn main() {} diff --git a/tests/ui/impl-trait/method-resolution3.current.stderr b/tests/ui/impl-trait/method-resolution3.current.stderr new file mode 100644 index 0000000000000..7407b489e324f --- /dev/null +++ b/tests/ui/impl-trait/method-resolution3.current.stderr @@ -0,0 +1,37 @@ +error[E0599]: no method named `bar` found for struct `Bar` in the current scope + --> $DIR/method-resolution3.rs:22:11 + | +LL | struct Bar(T); + | ------------- method `bar` not found for this struct +... +LL | x.bar(); + | ^^^ method not found in `Bar` + | + = note: the method was found for + - `Bar` + - `Bar` + +error[E0391]: cycle detected when computing type of opaque `foo::{opaque#0}` + --> $DIR/method-resolution3.rs:18:24 + | +LL | fn foo(x: bool) -> Bar { + | ^^^^^^^^^^ + | +note: ...which requires type-checking `foo`... + --> $DIR/method-resolution3.rs:22:9 + | +LL | x.bar(); + | ^ + = note: ...which requires evaluating trait selection obligation `Bar: core::marker::Unpin`... + = note: ...which again requires computing type of opaque `foo::{opaque#0}`, completing the cycle +note: cycle used when computing type of `foo::{opaque#0}` + --> $DIR/method-resolution3.rs:18:24 + | +LL | fn foo(x: bool) -> Bar { + | ^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0391, E0599. +For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/method-resolution3.next.stderr b/tests/ui/impl-trait/method-resolution3.next.stderr new file mode 100644 index 0000000000000..53b77c620ba0e --- /dev/null +++ b/tests/ui/impl-trait/method-resolution3.next.stderr @@ -0,0 +1,20 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/method-resolution3.rs:22:11 + | +LL | x.bar(); + | ^^^ multiple `bar` found + | +note: candidate #1 is defined in an impl for the type `Bar` + --> $DIR/method-resolution3.rs:15:5 + | +LL | fn bar(self) {} + | ^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Bar` + --> $DIR/method-resolution3.rs:11:5 + | +LL | fn bar(self) {} + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/impl-trait/method-resolution3.rs b/tests/ui/impl-trait/method-resolution3.rs new file mode 100644 index 0000000000000..8474e2da7dbb9 --- /dev/null +++ b/tests/ui/impl-trait/method-resolution3.rs @@ -0,0 +1,29 @@ +//! Check that we consider `Bar` to successfully unify +//! with both `Bar` and `Bar` (in isolation), so we bail +//! out with ambiguity. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +struct Bar(T); + +impl Bar { + fn bar(self) {} +} + +impl Bar { + fn bar(self) {} +} + +fn foo(x: bool) -> Bar { + //[current]~^ ERROR: cycle + if x { + let x = foo(false); + x.bar(); + //[current]~^ ERROR: no method named `bar` + //[next]~^^ ERROR: multiple applicable items in scope + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/method-resolution4.next.stderr b/tests/ui/impl-trait/method-resolution4.next.stderr new file mode 100644 index 0000000000000..b48de0af3579d --- /dev/null +++ b/tests/ui/impl-trait/method-resolution4.next.stderr @@ -0,0 +1,22 @@ +error[E0282]: type annotations needed + --> $DIR/method-resolution4.rs:13:9 + | +LL | foo(false).next().unwrap(); + | ^^^^^^^^^^ cannot infer type + +error[E0308]: mismatched types + --> $DIR/method-resolution4.rs:16:5 + | +LL | fn foo(b: bool) -> impl Iterator { + | ------------------------ the expected opaque type +... +LL | std::iter::empty() + | ^^^^^^^^^^^^^^^^^^ types differ + | + = note: expected opaque type `impl Iterator` + found struct `std::iter::Empty<_>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/method-resolution4.rs b/tests/ui/impl-trait/method-resolution4.rs new file mode 100644 index 0000000000000..3578db7cb55f3 --- /dev/null +++ b/tests/ui/impl-trait/method-resolution4.rs @@ -0,0 +1,20 @@ +//! The recursive method call yields the opaque type. The +//! `next` method call then constrains the hidden type to `&mut _` +//! because `next` takes `&mut self`. We never resolve the inference +//! variable, but get a type mismatch when comparing `&mut _` with +//! `std::iter::Empty`. + +//@[current] check-pass +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +fn foo(b: bool) -> impl Iterator { + if b { + foo(false).next().unwrap(); + //[next]~^ type annotations needed + } + std::iter::empty() + //[next]~^ mismatched types +} + +fn main() {} diff --git a/tests/ui/impl-trait/recursive-parent-trait-method-call.rs b/tests/ui/impl-trait/recursive-parent-trait-method-call.rs new file mode 100644 index 0000000000000..4da9a06a4659b --- /dev/null +++ b/tests/ui/impl-trait/recursive-parent-trait-method-call.rs @@ -0,0 +1,42 @@ +//! This test checks that we can resolve the `boxed` method call to `FutureExt`, +//! because we know that the anonymous future does not implement `StreamExt`. + +//@ edition: 2021 +//@ check-pass + +use std::future::Future; +use std::pin::Pin; + +trait FutureExt: Future + Sized + Send + 'static { + fn boxed(self) -> Pin + Send + 'static>> { + Box::pin(self) + } +} + +trait StreamExt: Future + Sized + Send + 'static { + fn boxed(self) -> Pin + Send + 'static>> { + Box::pin(self) + } +} + +impl FutureExt for T {} + +fn go(i: usize) -> impl Future + Send + 'static { + async move { + if i != 0 { + spawn(async move { + let fut = go(i - 1).boxed(); + fut.await; + }) + .await; + } + } +} + +pub fn spawn( + _: impl Future + Send + 'static, +) -> impl Future + Send + 'static { + async move { todo!() } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/method_resolution.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr new file mode 100644 index 0000000000000..a9c05ad33424d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `bar` found for struct `Bar` in the current scope + --> $DIR/method_resolution.rs:21:14 + | +LL | struct Bar(T); + | ------------- method `bar` not found for this struct +... +LL | self.bar() + | ^^^ method not found in `Bar` + | + = note: the method was found for + - `Bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr new file mode 100644 index 0000000000000..6b34358a56ea3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `bar` found for struct `Bar` in the current scope + --> $DIR/method_resolution.rs:21:14 + | +LL | struct Bar(T); + | ------------- method `bar` not found for this struct +... +LL | self.bar() + | ^^^ method cannot be called on `Bar` due to unsatisfied trait bounds + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution.rs b/tests/ui/type-alias-impl-trait/method_resolution.rs new file mode 100644 index 0000000000000..f636aba15c0c4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution.rs @@ -0,0 +1,30 @@ +//! `Bar::foo` is not defining `Foo`, so it cannot rely on the fact that +//! `u32` is the hidden type of `Foo` to call `bar` + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +#![feature(type_alias_impl_trait)] + +type Foo = impl Sized; + +struct Bar(T); + +impl Bar { + fn bar(mut self) { + self.0 = 42_u32; + } +} + +impl Bar { + fn foo(self) { + self.bar() + //~^ ERROR: no method named `bar` + } +} + +fn foo() -> Foo { + 42_u32 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr new file mode 100644 index 0000000000000..e68ea70a8ef48 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr @@ -0,0 +1,36 @@ +error[E0599]: no method named `foo` found for struct `Bar` in the current scope + --> $DIR/method_resolution2.rs:17:14 + | +LL | struct Bar(T); + | ------------- method `foo` not found for this struct +... +LL | self.foo() + | ^^^ method not found in `Bar` + | + = note: the method was found for + - `Bar` + +error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}` + --> $DIR/method_resolution2.rs:10:12 + | +LL | type Foo = impl Sized; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `::bar`... + --> $DIR/method_resolution2.rs:17:9 + | +LL | self.foo() + | ^^^^ + = note: ...which requires evaluating trait selection obligation `Bar: core::marker::Unpin`... + = note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle +note: cycle used when computing type of `Foo::{opaque#0}` + --> $DIR/method_resolution2.rs:10:12 + | +LL | type Foo = impl Sized; + | ^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0391, E0599. +For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.rs b/tests/ui/type-alias-impl-trait/method_resolution2.rs new file mode 100644 index 0000000000000..d252f8640d460 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution2.rs @@ -0,0 +1,30 @@ +//! Check that we do not unify `Bar` with `Bar`, even though the +//! `foo` method call can be resolved unambiguously by doing so. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +#![feature(type_alias_impl_trait)] + +type Foo = impl Sized; +//[current]~^ ERROR: cycle + +struct Bar(T); + +impl Bar { + fn bar(self) { + self.foo() + //[current]~^ ERROR: no method named `foo` + } +} + +impl Bar { + fn foo(self) {} +} + +fn foo() -> Foo { + 42_u32 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr new file mode 100644 index 0000000000000..e992d059daf7d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr @@ -0,0 +1,21 @@ +error[E0307]: invalid `self` parameter type: `Bar` + --> $DIR/method_resolution3.rs:16:18 + | +LL | fn bar(self: Bar) { + | ^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0307]: invalid `self` parameter type: `&Bar` + --> $DIR/method_resolution3.rs:21:18 + | +LL | fn baz(self: &Bar) { + | ^^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr new file mode 100644 index 0000000000000..9272017cdf5d1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr @@ -0,0 +1,15 @@ +error[E0271]: type mismatch resolving `Foo == u32` + --> $DIR/method_resolution3.rs:16:18 + | +LL | fn bar(self: Bar) { + | ^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `Foo == u32` + --> $DIR/method_resolution3.rs:21:18 + | +LL | fn baz(self: &Bar) { + | ^^^^^^^^^ types differ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.rs b/tests/ui/type-alias-impl-trait/method_resolution3.rs new file mode 100644 index 0000000000000..447f3144b822c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution3.rs @@ -0,0 +1,36 @@ +//! Check that one cannot use arbitrary self types where a generic parameter +//! mismatches with an opaque type. In theory this could unify with the opaque +//! type, registering the generic parameter as the hidden type of the opaque type. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +#![feature(type_alias_impl_trait, arbitrary_self_types)] + +type Foo = impl Copy; + +#[derive(Copy, Clone)] +struct Bar(T); + +impl Bar { + fn bar(self: Bar) { + //[current]~^ ERROR: invalid `self` parameter + //[next]~^^ ERROR: type mismatch resolving `Foo == u32` + self.foo() + } + fn baz(self: &Bar) { + //[current]~^ ERROR: invalid `self` parameter + //[next]~^^ ERROR: type mismatch resolving `Foo == u32` + self.foo() + } +} + +impl Bar { + fn foo(self) {} +} + +fn foo() -> Foo { + 42_u32 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr new file mode 100644 index 0000000000000..3a2ca18f89097 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr @@ -0,0 +1,21 @@ +error[E0307]: invalid `self` parameter type: `Bar` + --> $DIR/method_resolution4.rs:27:18 + | +LL | fn foo(self: Bar) { + | ^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0307]: invalid `self` parameter type: `&Bar` + --> $DIR/method_resolution4.rs:32:20 + | +LL | fn foomp(self: &Bar) { + | ^^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr new file mode 100644 index 0000000000000..33ed2800ebe0c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr @@ -0,0 +1,15 @@ +error[E0271]: type mismatch resolving `u32 == Foo` + --> $DIR/method_resolution4.rs:27:18 + | +LL | fn foo(self: Bar) { + | ^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `u32 == Foo` + --> $DIR/method_resolution4.rs:32:20 + | +LL | fn foomp(self: &Bar) { + | ^^^^^^^^^ types differ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.rs b/tests/ui/type-alias-impl-trait/method_resolution4.rs new file mode 100644 index 0000000000000..42ed04b3c30f6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution4.rs @@ -0,0 +1,39 @@ +//! Check that one cannot use arbitrary self types where a generic parameter +//! mismatches with an opaque type. In theory this could unify with the opaque +//! type, registering the generic parameter as the hidden type of the opaque type. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +#![feature(type_alias_impl_trait, arbitrary_self_types)] + +mod foo { + pub type Foo = impl Copy; + + fn foo() -> Foo { + 42_u32 + } +} +use foo::Foo; + +#[derive(Copy, Clone)] +struct Bar(T); + +impl Bar { + fn bar(self) {} +} + +impl Bar { + fn foo(self: Bar) { + //[current]~^ ERROR: invalid `self` parameter + //[next]~^^ ERROR: type mismatch resolving `u32 == Foo` + self.bar() + } + fn foomp(self: &Bar) { + //[current]~^ ERROR: invalid `self` parameter + //[next]~^^ ERROR: type mismatch resolving `u32 == Foo` + self.bar() + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr new file mode 100644 index 0000000000000..193e6e1470957 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `bar` found for struct `Bar` in the current scope + --> $DIR/method_resolution5.rs:25:14 + | +LL | struct Bar(T); + | ------------- method `bar` not found for this struct +... +LL | self.bar() + | ^^^ method not found in `Bar` + | + = note: the method was found for + - `Bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.rs b/tests/ui/type-alias-impl-trait/method_resolution5.rs new file mode 100644 index 0000000000000..69335c9deded3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution5.rs @@ -0,0 +1,34 @@ +//! Even though `Bar::foo` is defining `Foo`, the old solver does +//! not figure out that `u32` is the hidden type of `Foo` to call `bar`. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +#![feature(type_alias_impl_trait)] + +type Foo = impl Sized; + +struct Bar(T); + +impl Bar { + fn bar(mut self) { + self.0 = 42_u32; + } +} + +impl Bar { + fn foo(self) + where + Foo:, + { + self.bar() + //[current]~^ ERROR: no method named `bar` + } +} + +fn foo() -> Foo { + 42_u32 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr new file mode 100644 index 0000000000000..f331da1af8793 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr @@ -0,0 +1,15 @@ +error: item does not constrain `Tait::{opaque#0}`, but has it in its signature + --> $DIR/method_resolution_trait_method_from_opaque.rs:24:8 + | +LL | fn foo(&mut self) { + | ^^^ + | + = note: consider moving the opaque type's declaration and defining uses into a separate module +note: this opaque type is in the signature + --> $DIR/method_resolution_trait_method_from_opaque.rs:17:13 + | +LL | type Tait = impl Iterator; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr new file mode 100644 index 0000000000000..2617ce124c105 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/method_resolution_trait_method_from_opaque.rs:26:9 + | +LL | self.bar.next().unwrap(); + | ^^^^^^^^ cannot infer type + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs new file mode 100644 index 0000000000000..b6adf08853f2f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs @@ -0,0 +1,31 @@ +//! This test demonstrates how method calls will attempt to unify an opaque type with a reference +//! if the method takes `&self` as its argument. This is almost never what is desired, as the user +//! would like to have method resolution happen on the opaque type instead of inferring the hidden +//! type. Once type-alias-impl-trait requires annotating which functions should constrain the hidden +//! type, this won't be as much of a problem, as most functions that do method calls on opaque types +//! won't also be the ones defining the hidden type. + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +#![feature(type_alias_impl_trait)] + +pub struct Foo { + bar: Tait, +} + +type Tait = impl Iterator; + +impl Foo { + pub fn new() -> Foo { + Foo { bar: std::iter::empty() } + } + + fn foo(&mut self) { + //[current]~^ ERROR: item does not constrain + self.bar.next().unwrap(); + //[next]~^ ERROR: type annotations needed + } +} + +fn main() {} From 9cf60ee9d33fadff387d83d09aef1ce43589e233 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 15 Apr 2024 11:37:09 +0000 Subject: [PATCH 3/3] Method resolution constrains hidden types instead of rejecting method candidates --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- .../rustc_hir_typeck/src/method/confirm.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 65 +++++++++---------- compiler/rustc_middle/src/traits/query.rs | 2 +- .../method-resolution.current.stderr | 36 ---------- tests/ui/impl-trait/method-resolution.rs | 9 +-- tests/ui/impl-trait/method-resolution2.rs | 2 +- .../method-resolution3.current.stderr | 43 ++++-------- .../impl-trait/method-resolution3.next.stderr | 2 +- tests/ui/impl-trait/method-resolution3.rs | 4 +- tests/ui/impl-trait/method-resolution4.rs | 2 +- tests/ui/methods/opaque_param_in_ufc.rs | 6 +- tests/ui/methods/opaque_param_in_ufc.stderr | 36 ---------- .../method_resolution2.current.stderr | 36 ---------- .../method_resolution2.rs | 6 +- .../method_resolution5.current.stderr | 15 ----- .../method_resolution5.rs | 3 +- 17 files changed, 58 insertions(+), 213 deletions(-) delete mode 100644 tests/ui/impl-trait/method-resolution.current.stderr delete mode 100644 tests/ui/methods/opaque_param_in_ufc.stderr delete mode 100644 tests/ui/type-alias-impl-trait/method_resolution2.current.stderr delete mode 100644 tests/ui/type-alias-impl-trait/method_resolution5.current.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 94e879ae9c3ed..9531c002829ea 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1418,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args)); let self_ty = self.normalize(span, self_ty); match self.at(&self.misc(span), self.param_env).eq( - DefineOpaqueTypes::No, + DefineOpaqueTypes::Yes, impl_ty, self_ty, ) { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 3c9a49e91a3f9..120e3239d1f1b 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -497,7 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { args, })), ); - match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) { + match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index e842bba34bf82..3986374a343f0 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -634,8 +634,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) { - debug!("assemble_probe: self_ty={:?}", self_ty); let raw_self_ty = self_ty.value.value; match *raw_self_ty.kind() { ty::Dynamic(data, ..) if let Some(p) = data.principal() => { @@ -713,13 +713,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) { if !self.impl_dups.insert(impl_def_id) { return; // already visited } - debug!("assemble_inherent_impl_probe {:?}", impl_def_id); - for item in self.impl_or_trait_item(impl_def_id) { if !self.has_applicable_self(&item) { // No receiver declared. Not a candidate. @@ -737,9 +736,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) { - debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty); - let principal = match self_ty.kind() { ty::Dynamic(ref data, ..) => Some(data), _ => None, @@ -768,9 +766,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }); } + #[instrument(level = "debug", skip(self))] fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) { // FIXME: do we want to commit to this behavior for param bounds? - debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty); let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| { let bound_predicate = predicate.kind(); @@ -826,6 +824,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn assemble_extension_candidates_for_traits_in_scope(&mut self) { let mut duplicates = FxHashSet::default(); let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id); @@ -842,6 +841,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn assemble_extension_candidates_for_all_traits(&mut self) { let mut duplicates = FxHashSet::default(); for trait_info in suggest::all_traits(self.tcx) { @@ -863,12 +863,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn assemble_extension_candidates_for_trait( &mut self, import_ids: &SmallVec<[LocalDefId; 1]>, trait_def_id: DefId, ) { - debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id); let trait_args = self.fresh_args_for_item(self.span, trait_def_id); let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args); @@ -958,6 +958,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /////////////////////////////////////////////////////////////////////////// // THE ACTUAL SEARCH + #[instrument(level = "debug", skip(self))] fn pick(mut self) -> PickResult<'tcx> { assert!(self.method_name.is_some()); @@ -1386,6 +1387,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + #[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)] fn consider_probe( &self, self_ty: Ty<'tcx>, @@ -1415,15 +1417,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { (xform_self_ty, xform_ret_ty) = self.xform_self_ty(probe.item, impl_ty, impl_args); xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty); - // FIXME: Make this `ocx.sup` once we define opaques more eagerly. - match self.at(cause, self.param_env).sup( - DefineOpaqueTypes::No, - xform_self_ty, - self_ty, - ) { - Ok(infer_ok) => { - ocx.register_infer_ok_obligations(infer_ok); - } + match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) { + Ok(()) => {} Err(err) => { debug!("--> cannot relate self-types {:?}", err); return ProbeResult::NoMatch; @@ -1484,19 +1479,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { (xform_self_ty, xform_ret_ty) = self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args); xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty); - // FIXME: Make this `ocx.sup` once we define opaques more eagerly. - match self.at(cause, self.param_env).sup( - DefineOpaqueTypes::No, - xform_self_ty, - self_ty, - ) { - Ok(infer_ok) => { - ocx.register_infer_ok_obligations(infer_ok); - } - Err(err) => { - debug!("--> cannot relate self-types {:?}", err); + match self_ty.kind() { + // HACK: opaque types will match anything for which their bounds hold. + // Thus we need to prevent them from trying to match the `&_` autoref + // candidates that get created for `&self` trait methods. + ty::Alias(ty::Opaque, alias_ty) + if self.infcx.can_define_opaque_ty(alias_ty.def_id) + && !xform_self_ty.is_ty_var() => + { return ProbeResult::NoMatch; } + _ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) { + Ok(()) => {} + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); + return ProbeResult::NoMatch; + } + }, } let obligation = traits::Obligation::new( self.tcx, @@ -1536,15 +1535,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { (xform_self_ty, xform_ret_ty) = self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args); xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty); - // FIXME: Make this `ocx.sup` once we define opaques more eagerly. - match self.at(cause, self.param_env).sup( - DefineOpaqueTypes::No, - xform_self_ty, - self_ty, - ) { - Ok(infer_ok) => { - ocx.register_infer_ok_obligations(infer_ok); - } + match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) { + Ok(()) => {} Err(err) => { debug!("--> cannot relate self-types {:?}", err); return ProbeResult::NoMatch; @@ -1665,6 +1657,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// Similarly to `probe_for_return_type`, this method attempts to find the best matching /// candidate method where the method name may have been misspelled. Similarly to other /// edit distance based suggestions, we provide at most one such suggestion. + #[instrument(level = "debug", skip(self))] pub(crate) fn probe_for_similar_candidate( &mut self, ) -> Result, MethodError<'tcx>> { diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 50b6c77e1b29d..4fad721ce9847 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -156,7 +156,7 @@ pub struct CandidateStep<'tcx> { #[derive(Copy, Clone, Debug, HashStable)] pub struct MethodAutoderefStepsResult<'tcx> { - /// The valid autoderef steps that could be find. + /// The valid autoderef steps that could be found. pub steps: &'tcx [CandidateStep<'tcx>], /// If Some(T), a type autoderef reported an error on. pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>, diff --git a/tests/ui/impl-trait/method-resolution.current.stderr b/tests/ui/impl-trait/method-resolution.current.stderr deleted file mode 100644 index 6d10693c8933b..0000000000000 --- a/tests/ui/impl-trait/method-resolution.current.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0599]: no method named `bar` found for struct `Bar` in the current scope - --> $DIR/method-resolution.rs:23:11 - | -LL | struct Bar(T); - | ------------- method `bar` not found for this struct -... -LL | x.bar(); - | ^^^ method not found in `Bar` - | - = note: the method was found for - - `Bar` - -error[E0391]: cycle detected when computing type of opaque `foo::{opaque#0}` - --> $DIR/method-resolution.rs:19:24 - | -LL | fn foo(x: bool) -> Bar { - | ^^^^^^^^^^ - | -note: ...which requires type-checking `foo`... - --> $DIR/method-resolution.rs:23:9 - | -LL | x.bar(); - | ^ - = note: ...which requires evaluating trait selection obligation `Bar: core::marker::Unpin`... - = note: ...which again requires computing type of opaque `foo::{opaque#0}`, completing the cycle -note: cycle used when computing type of `foo::{opaque#0}` - --> $DIR/method-resolution.rs:19:24 - | -LL | fn foo(x: bool) -> Bar { - | ^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0391, E0599. -For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/method-resolution.rs b/tests/ui/impl-trait/method-resolution.rs index 07618aa64085d..60fbacd86462b 100644 --- a/tests/ui/impl-trait/method-resolution.rs +++ b/tests/ui/impl-trait/method-resolution.rs @@ -1,10 +1,9 @@ -//! Check that we do not constrain hidden types during method resolution. -//! Otherwise we'd pick up that calling `bar` can be satisfied iff `u32` -//! is the hidden type of the RPIT. +//! Since there is only one possible `bar` method, we invoke it and subsequently +//! constrain `foo`'s RPIT to `u32`. //@ revisions: current next //@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass trait Trait {} @@ -17,11 +16,9 @@ impl Bar { } fn foo(x: bool) -> Bar { - //[current]~^ ERROR: cycle detected if x { let x = foo(false); x.bar(); - //[current]~^ ERROR: no method named `bar` found } todo!() } diff --git a/tests/ui/impl-trait/method-resolution2.rs b/tests/ui/impl-trait/method-resolution2.rs index 2930b42b8bca0..88d4f3d9896c7 100644 --- a/tests/ui/impl-trait/method-resolution2.rs +++ b/tests/ui/impl-trait/method-resolution2.rs @@ -1,5 +1,5 @@ //! Check that the method call does not constrain the RPIT to `i32`, even though -//! `i32` is the only trait that satisfies the RPIT's trait bounds. +//! `i32` is the only type that satisfies the RPIT's trait bounds. //@ revisions: current next //@[next] compile-flags: -Znext-solver diff --git a/tests/ui/impl-trait/method-resolution3.current.stderr b/tests/ui/impl-trait/method-resolution3.current.stderr index 7407b489e324f..87dd862ef8f4f 100644 --- a/tests/ui/impl-trait/method-resolution3.current.stderr +++ b/tests/ui/impl-trait/method-resolution3.current.stderr @@ -1,37 +1,20 @@ -error[E0599]: no method named `bar` found for struct `Bar` in the current scope - --> $DIR/method-resolution3.rs:22:11 +error[E0034]: multiple applicable items in scope + --> $DIR/method-resolution3.rs:21:11 | -LL | struct Bar(T); - | ------------- method `bar` not found for this struct -... LL | x.bar(); - | ^^^ method not found in `Bar` + | ^^^ multiple `bar` found | - = note: the method was found for - - `Bar` - - `Bar` - -error[E0391]: cycle detected when computing type of opaque `foo::{opaque#0}` - --> $DIR/method-resolution3.rs:18:24 - | -LL | fn foo(x: bool) -> Bar { - | ^^^^^^^^^^ +note: candidate #1 is defined in an impl for the type `Bar` + --> $DIR/method-resolution3.rs:15:5 | -note: ...which requires type-checking `foo`... - --> $DIR/method-resolution3.rs:22:9 - | -LL | x.bar(); - | ^ - = note: ...which requires evaluating trait selection obligation `Bar: core::marker::Unpin`... - = note: ...which again requires computing type of opaque `foo::{opaque#0}`, completing the cycle -note: cycle used when computing type of `foo::{opaque#0}` - --> $DIR/method-resolution3.rs:18:24 +LL | fn bar(self) {} + | ^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Bar` + --> $DIR/method-resolution3.rs:11:5 | -LL | fn foo(x: bool) -> Bar { - | ^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information +LL | fn bar(self) {} + | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0391, E0599. -For more information about an error, try `rustc --explain E0391`. +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/impl-trait/method-resolution3.next.stderr b/tests/ui/impl-trait/method-resolution3.next.stderr index 53b77c620ba0e..87dd862ef8f4f 100644 --- a/tests/ui/impl-trait/method-resolution3.next.stderr +++ b/tests/ui/impl-trait/method-resolution3.next.stderr @@ -1,5 +1,5 @@ error[E0034]: multiple applicable items in scope - --> $DIR/method-resolution3.rs:22:11 + --> $DIR/method-resolution3.rs:21:11 | LL | x.bar(); | ^^^ multiple `bar` found diff --git a/tests/ui/impl-trait/method-resolution3.rs b/tests/ui/impl-trait/method-resolution3.rs index 8474e2da7dbb9..8c47ef4fc75c7 100644 --- a/tests/ui/impl-trait/method-resolution3.rs +++ b/tests/ui/impl-trait/method-resolution3.rs @@ -16,12 +16,10 @@ impl Bar { } fn foo(x: bool) -> Bar { - //[current]~^ ERROR: cycle if x { let x = foo(false); x.bar(); - //[current]~^ ERROR: no method named `bar` - //[next]~^^ ERROR: multiple applicable items in scope + //~^ ERROR: multiple applicable items in scope } todo!() } diff --git a/tests/ui/impl-trait/method-resolution4.rs b/tests/ui/impl-trait/method-resolution4.rs index 3578db7cb55f3..91884eb59fd63 100644 --- a/tests/ui/impl-trait/method-resolution4.rs +++ b/tests/ui/impl-trait/method-resolution4.rs @@ -4,9 +4,9 @@ //! variable, but get a type mismatch when comparing `&mut _` with //! `std::iter::Empty`. -//@[current] check-pass //@ revisions: current next //@[next] compile-flags: -Znext-solver +//@[current] check-pass fn foo(b: bool) -> impl Iterator { if b { diff --git a/tests/ui/methods/opaque_param_in_ufc.rs b/tests/ui/methods/opaque_param_in_ufc.rs index a4b27a0131fd0..b170e6805f646 100644 --- a/tests/ui/methods/opaque_param_in_ufc.rs +++ b/tests/ui/methods/opaque_param_in_ufc.rs @@ -1,4 +1,7 @@ #![feature(type_alias_impl_trait)] + +//@ check-pass + struct Foo(T); impl Foo { @@ -15,14 +18,11 @@ fn bar() -> Bar { impl Foo { fn foo() -> Bar { Self::method(); - //~^ ERROR: no function or associated item named `method` found for struct `Foo` Foo::::method(); - //~^ ERROR: no function or associated item named `method` found for struct `Foo` let x = Foo(bar()); Foo::method2(x); let x = Self(bar()); Self::method2(x); - //~^ ERROR: no function or associated item named `method2` found for struct `Foo` todo!() } } diff --git a/tests/ui/methods/opaque_param_in_ufc.stderr b/tests/ui/methods/opaque_param_in_ufc.stderr deleted file mode 100644 index 7e5bbbac8a9ab..0000000000000 --- a/tests/ui/methods/opaque_param_in_ufc.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0599]: no function or associated item named `method` found for struct `Foo` in the current scope - --> $DIR/opaque_param_in_ufc.rs:17:15 - | -LL | struct Foo(T); - | ------------- function or associated item `method` not found for this struct -... -LL | Self::method(); - | ^^^^^^ function or associated item not found in `Foo` - | - = note: the function or associated item was found for - - `Foo` - -error[E0599]: no function or associated item named `method` found for struct `Foo` in the current scope - --> $DIR/opaque_param_in_ufc.rs:19:21 - | -LL | struct Foo(T); - | ------------- function or associated item `method` not found for this struct -... -LL | Foo::::method(); - | ^^^^^^ function or associated item not found in `Foo` - | - = note: the function or associated item was found for - - `Foo` - -error[E0599]: no function or associated item named `method2` found for struct `Foo` in the current scope - --> $DIR/opaque_param_in_ufc.rs:24:15 - | -LL | struct Foo(T); - | ------------- function or associated item `method2` not found for this struct -... -LL | Self::method2(x); - | ^^^^^^^ function or associated item not found in `Foo` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr deleted file mode 100644 index e68ea70a8ef48..0000000000000 --- a/tests/ui/type-alias-impl-trait/method_resolution2.current.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0599]: no method named `foo` found for struct `Bar` in the current scope - --> $DIR/method_resolution2.rs:17:14 - | -LL | struct Bar(T); - | ------------- method `foo` not found for this struct -... -LL | self.foo() - | ^^^ method not found in `Bar` - | - = note: the method was found for - - `Bar` - -error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}` - --> $DIR/method_resolution2.rs:10:12 - | -LL | type Foo = impl Sized; - | ^^^^^^^^^^ - | -note: ...which requires type-checking `::bar`... - --> $DIR/method_resolution2.rs:17:9 - | -LL | self.foo() - | ^^^^ - = note: ...which requires evaluating trait selection obligation `Bar: core::marker::Unpin`... - = note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle -note: cycle used when computing type of `Foo::{opaque#0}` - --> $DIR/method_resolution2.rs:10:12 - | -LL | type Foo = impl Sized; - | ^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0391, E0599. -For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.rs b/tests/ui/type-alias-impl-trait/method_resolution2.rs index d252f8640d460..f69661db79922 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution2.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution2.rs @@ -1,21 +1,19 @@ -//! Check that we do not unify `Bar` with `Bar`, even though the +//! Check that we do unify `Bar` with `Bar`, as the //! `foo` method call can be resolved unambiguously by doing so. //@ revisions: current next //@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass #![feature(type_alias_impl_trait)] type Foo = impl Sized; -//[current]~^ ERROR: cycle struct Bar(T); impl Bar { fn bar(self) { self.foo() - //[current]~^ ERROR: no method named `foo` } } diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr deleted file mode 100644 index 193e6e1470957..0000000000000 --- a/tests/ui/type-alias-impl-trait/method_resolution5.current.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0599]: no method named `bar` found for struct `Bar` in the current scope - --> $DIR/method_resolution5.rs:25:14 - | -LL | struct Bar(T); - | ------------- method `bar` not found for this struct -... -LL | self.bar() - | ^^^ method not found in `Bar` - | - = note: the method was found for - - `Bar` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.rs b/tests/ui/type-alias-impl-trait/method_resolution5.rs index 69335c9deded3..64355e4560de2 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution5.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution5.rs @@ -3,7 +3,7 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass #![feature(type_alias_impl_trait)] @@ -23,7 +23,6 @@ impl Bar { Foo:, { self.bar() - //[current]~^ ERROR: no method named `bar` } }