diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 2230528a5ae11..279e9fc5df379 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1712,7 +1712,15 @@ fn receiver_is_valid<'tcx>( let cause = ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver); - let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty); + let can_eq_self = |ty| { + wfcx.infcx.probe(|_| { + let ocx = ObligationCtxt::new(wfcx.infcx); + let Ok(()) = ocx.eq(&ObligationCause::dummy(), wfcx.param_env, self_ty, ty) else { + return false; + }; + ocx.select_where_possible().is_empty() + }) + }; // `self: Self` is always valid. if can_eq_self(receiver_ty) { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index a3cf588da1c02..361eaf3d419bf 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -767,6 +767,8 @@ impl<'tcx> InferCtxt<'tcx> { .collect() } + // FIXME(-Znext-solver): Get rid of this method, it's never correct. Either that, + // or we need to process the obligations. pub fn can_sub(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool where T: at::ToTrace<'tcx>, @@ -779,6 +781,8 @@ impl<'tcx> InferCtxt<'tcx> { }) } + // FIXME(-Znext-solver): Get rid of this method, it's never correct. Either that, + // or we need to process the obligations. pub fn can_eq(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool where T: at::ToTrace<'tcx>, diff --git a/tests/ui/traits/next-solver/typeck/receiver-self-ty-check-eq.rs b/tests/ui/traits/next-solver/typeck/receiver-self-ty-check-eq.rs new file mode 100644 index 0000000000000..f8c8a17b7e503 --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/receiver-self-ty-check-eq.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Fixes a regression in `receiver_is_valid` in wfcheck where we were using +// `InferCtxt::can_eq` instead of processing alias-relate goals, leading to false +// positives, not deref'ing enough steps to check the receiver is valid. + +trait Mirror { + type Mirror: ?Sized; +} +impl Mirror for T { + type Mirror = T; +} + +trait Foo { + fn foo(&self) {} +} + +impl Foo for <() as Mirror>::Mirror { + fn foo(&self) {} +} + +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 index e992d059daf7d..09efd7a9e7e2d 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr @@ -8,7 +8,7 @@ LL | fn bar(self: Bar) { = 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 + --> $DIR/method_resolution3.rs:20:18 | LL | fn baz(self: &Bar) { | ^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr index 9272017cdf5d1..09efd7a9e7e2d 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr @@ -1,15 +1,21 @@ -error[E0271]: type mismatch resolving `Foo == u32` +error[E0307]: invalid `self` parameter type: `Bar` --> $DIR/method_resolution3.rs:16:18 | LL | fn bar(self: Bar) { - | ^^^^^^^^ types differ + | ^^^^^^^^ + | + = 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[E0271]: type mismatch resolving `Foo == u32` - --> $DIR/method_resolution3.rs:21:18 +error[E0307]: invalid `self` parameter type: `&Bar` + --> $DIR/method_resolution3.rs:20:18 | LL | fn baz(self: &Bar) { - | ^^^^^^^^^ types differ + | ^^^^^^^^^ + | + = 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 E0271`. +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.rs b/tests/ui/type-alias-impl-trait/method_resolution3.rs index 447f3144b822c..0e6176bfe03c7 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution3.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution3.rs @@ -14,13 +14,11 @@ struct Bar(T); impl Bar { fn bar(self: Bar) { - //[current]~^ ERROR: invalid `self` parameter - //[next]~^^ ERROR: type mismatch resolving `Foo == u32` + //~^ ERROR: invalid `self` parameter self.foo() } fn baz(self: &Bar) { - //[current]~^ ERROR: invalid `self` parameter - //[next]~^^ ERROR: type mismatch resolving `Foo == u32` + //~^ ERROR: invalid `self` parameter self.foo() } } diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr index 3a2ca18f89097..8ffdb21f2517b 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr @@ -8,7 +8,7 @@ LL | fn foo(self: Bar) { = 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 + --> $DIR/method_resolution4.rs:31:20 | LL | fn foomp(self: &Bar) { | ^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr index 33ed2800ebe0c..8ffdb21f2517b 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr @@ -1,15 +1,21 @@ -error[E0271]: type mismatch resolving `u32 == Foo` +error[E0307]: invalid `self` parameter type: `Bar` --> $DIR/method_resolution4.rs:27:18 | LL | fn foo(self: Bar) { - | ^^^^^^^^ types differ + | ^^^^^^^^ + | + = 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[E0271]: type mismatch resolving `u32 == Foo` - --> $DIR/method_resolution4.rs:32:20 +error[E0307]: invalid `self` parameter type: `&Bar` + --> $DIR/method_resolution4.rs:31:20 | LL | fn foomp(self: &Bar) { - | ^^^^^^^^^ types differ + | ^^^^^^^^^ + | + = 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 E0271`. +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.rs b/tests/ui/type-alias-impl-trait/method_resolution4.rs index 42ed04b3c30f6..f33b4e473ae86 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution4.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution4.rs @@ -25,13 +25,11 @@ impl Bar { impl Bar { fn foo(self: Bar) { - //[current]~^ ERROR: invalid `self` parameter - //[next]~^^ ERROR: type mismatch resolving `u32 == Foo` + //~^ ERROR: invalid `self` parameter self.bar() } fn foomp(self: &Bar) { - //[current]~^ ERROR: invalid `self` parameter - //[next]~^^ ERROR: type mismatch resolving `u32 == Foo` + //~^ ERROR: invalid `self` parameter self.bar() } }