Skip to content

Commit ce608d4

Browse files
Process alias-relate obligations when proving receiver_is_valid
1 parent ef3d6fd commit ce608d4

File tree

9 files changed

+66
-23
lines changed

9 files changed

+66
-23
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1712,7 +1712,15 @@ fn receiver_is_valid<'tcx>(
17121712
let cause =
17131713
ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
17141714

1715-
let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty);
1715+
let can_eq_self = |ty| {
1716+
wfcx.infcx.probe(|_| {
1717+
let ocx = ObligationCtxt::new(wfcx.infcx);
1718+
let Ok(()) = ocx.eq(&ObligationCause::dummy(), wfcx.param_env, self_ty, ty) else {
1719+
return false;
1720+
};
1721+
ocx.select_where_possible().is_empty()
1722+
})
1723+
};
17161724

17171725
// `self: Self` is always valid.
17181726
if can_eq_self(receiver_ty) {

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,8 @@ impl<'tcx> InferCtxt<'tcx> {
767767
.collect()
768768
}
769769

770+
// FIXME(-Znext-solver): Get rid of this method, it's never correct. Either that,
771+
// or we need to process the obligations.
770772
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool
771773
where
772774
T: at::ToTrace<'tcx>,
@@ -779,6 +781,8 @@ impl<'tcx> InferCtxt<'tcx> {
779781
})
780782
}
781783

784+
// FIXME(-Znext-solver): Get rid of this method, it's never correct. Either that,
785+
// or we need to process the obligations.
782786
pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
783787
where
784788
T: at::ToTrace<'tcx>,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ compile-flags: -Znext-solver
2+
//@ check-pass
3+
4+
// Fixes a regression in `receiver_is_valid` in wfcheck where we were using
5+
// `InferCtxt::can_eq` instead of processing alias-relate goals, leading to false
6+
// positives, not deref'ing enough steps to check the receiver is valid.
7+
8+
trait Mirror {
9+
type Mirror: ?Sized;
10+
}
11+
impl<T: ?Sized> Mirror for T {
12+
type Mirror = T;
13+
}
14+
15+
trait Foo {
16+
fn foo(&self) {}
17+
}
18+
19+
impl Foo for <() as Mirror>::Mirror {
20+
fn foo(&self) {}
21+
}
22+
23+
fn main() {}

tests/ui/type-alias-impl-trait/method_resolution3.current.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | fn bar(self: Bar<u32>) {
88
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
99

1010
error[E0307]: invalid `self` parameter type: `&Bar<u32>`
11-
--> $DIR/method_resolution3.rs:21:18
11+
--> $DIR/method_resolution3.rs:20:18
1212
|
1313
LL | fn baz(self: &Bar<u32>) {
1414
| ^^^^^^^^^
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1-
error[E0271]: type mismatch resolving `Foo == u32`
1+
error[E0307]: invalid `self` parameter type: `Bar<u32>`
22
--> $DIR/method_resolution3.rs:16:18
33
|
44
LL | fn bar(self: Bar<u32>) {
5-
| ^^^^^^^^ types differ
5+
| ^^^^^^^^
6+
|
7+
= note: type of `self` must be `Self` or a type that dereferences to it
8+
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
69

7-
error[E0271]: type mismatch resolving `Foo == u32`
8-
--> $DIR/method_resolution3.rs:21:18
10+
error[E0307]: invalid `self` parameter type: `&Bar<u32>`
11+
--> $DIR/method_resolution3.rs:20:18
912
|
1013
LL | fn baz(self: &Bar<u32>) {
11-
| ^^^^^^^^^ types differ
14+
| ^^^^^^^^^
15+
|
16+
= note: type of `self` must be `Self` or a type that dereferences to it
17+
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
1218

1319
error: aborting due to 2 previous errors
1420

15-
For more information about this error, try `rustc --explain E0271`.
21+
For more information about this error, try `rustc --explain E0307`.

tests/ui/type-alias-impl-trait/method_resolution3.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@ struct Bar<T>(T);
1414

1515
impl Bar<Foo> {
1616
fn bar(self: Bar<u32>) {
17-
//[current]~^ ERROR: invalid `self` parameter
18-
//[next]~^^ ERROR: type mismatch resolving `Foo == u32`
17+
//~^ ERROR: invalid `self` parameter
1918
self.foo()
2019
}
2120
fn baz(self: &Bar<u32>) {
22-
//[current]~^ ERROR: invalid `self` parameter
23-
//[next]~^^ ERROR: type mismatch resolving `Foo == u32`
21+
//~^ ERROR: invalid `self` parameter
2422
self.foo()
2523
}
2624
}

tests/ui/type-alias-impl-trait/method_resolution4.current.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | fn foo(self: Bar<Foo>) {
88
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
99

1010
error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
11-
--> $DIR/method_resolution4.rs:32:20
11+
--> $DIR/method_resolution4.rs:31:20
1212
|
1313
LL | fn foomp(self: &Bar<Foo>) {
1414
| ^^^^^^^^^
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1-
error[E0271]: type mismatch resolving `u32 == Foo`
1+
error[E0307]: invalid `self` parameter type: `Bar<Foo>`
22
--> $DIR/method_resolution4.rs:27:18
33
|
44
LL | fn foo(self: Bar<Foo>) {
5-
| ^^^^^^^^ types differ
5+
| ^^^^^^^^
6+
|
7+
= note: type of `self` must be `Self` or a type that dereferences to it
8+
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
69

7-
error[E0271]: type mismatch resolving `u32 == Foo`
8-
--> $DIR/method_resolution4.rs:32:20
10+
error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
11+
--> $DIR/method_resolution4.rs:31:20
912
|
1013
LL | fn foomp(self: &Bar<Foo>) {
11-
| ^^^^^^^^^ types differ
14+
| ^^^^^^^^^
15+
|
16+
= note: type of `self` must be `Self` or a type that dereferences to it
17+
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
1218

1319
error: aborting due to 2 previous errors
1420

15-
For more information about this error, try `rustc --explain E0271`.
21+
For more information about this error, try `rustc --explain E0307`.

tests/ui/type-alias-impl-trait/method_resolution4.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@ impl Bar<Foo> {
2525

2626
impl Bar<u32> {
2727
fn foo(self: Bar<Foo>) {
28-
//[current]~^ ERROR: invalid `self` parameter
29-
//[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
28+
//~^ ERROR: invalid `self` parameter
3029
self.bar()
3130
}
3231
fn foomp(self: &Bar<Foo>) {
33-
//[current]~^ ERROR: invalid `self` parameter
34-
//[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
32+
//~^ ERROR: invalid `self` parameter
3533
self.bar()
3634
}
3735
}

0 commit comments

Comments
 (0)