Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit fe30d25

Browse files
committed
Auto merge of rust-lang#123962 - oli-obk:define_opaque_types5, r=<try>
change method resolution to constrain hidden types instead of rejecting method candidates Some of these are in probes and may affect inference. This is therefore a breaking change. This allows new code to compile on stable: ```rust trait Trait {} impl Trait for u32 {} struct Bar<T>(T); impl Bar<u32> { fn foo(self) {} } fn foo(x: bool) -> Bar<impl Sized> { if x { let x = foo(false); x.foo(); //^ this used to not find the `foo` method, because while we did equate `x`'s type with possible candidates, we didn't allow opaque type inference while doing so } todo!() } ``` But it is also a breaking change, since `&self` and `&mut self` method calls on recursive RPIT function calls now constrain the hidden type to `&_` and `&mut _` respectively. This is not what users really expect or want from this, but there's way around this. r? `@compiler-errors` fixes rust-lang#121404 cc rust-lang#116652
2 parents 0230848 + af980d5 commit fe30d25

33 files changed

+580
-46
lines changed

compiler/rustc_data_structures/src/obligation_forest/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,10 @@ impl<O: ForestObligation> ObligationForest<O> {
359359
Entry::Vacant(v) => {
360360
let obligation_tree_id = match parent {
361361
Some(parent_index) => self.nodes[parent_index].obligation_tree_id,
362-
None => self.obligation_tree_id_generator.next().unwrap(),
362+
// FIXME(type_alias_impl_trait): with `#[defines]` attributes required to define hidden
363+
// types we can convert this back to a `next` method call, as this function shouldn't be
364+
// defining a hidden type anyway.
365+
None => Iterator::next(&mut self.obligation_tree_id_generator).unwrap(),
363366
};
364367

365368
let already_failed = parent.is_some()

compiler/rustc_hir_typeck/src/callee.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
637637
return;
638638
};
639639

640-
let pick = self.confirm_method(
640+
let pick = self.confirm_method_for_diagnostic(
641641
call_expr.span,
642642
callee_expr,
643643
call_expr,

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14481448
let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
14491449
let self_ty = self.normalize(span, self_ty);
14501450
match self.at(&self.misc(span), self.param_env).eq(
1451-
DefineOpaqueTypes::No,
1451+
DefineOpaqueTypes::Yes,
14521452
impl_ty,
14531453
self_ty,
14541454
) {

compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
499499
args,
500500
})),
501501
);
502-
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
502+
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) {
503503
Ok(InferOk { obligations, value: () }) => {
504504
self.register_predicates(obligations);
505505
}

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1488,7 +1488,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14881488
self.probe(|_| {
14891489
// First check that the self type can be related.
14901490
let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env).sup(
1491-
DefineOpaqueTypes::No,
1491+
DefineOpaqueTypes::Yes,
14921492
probe.xform_self_ty,
14931493
self_ty,
14941494
) {

tests/ui/impl-trait/issues/issue-70877.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ fn ham() -> Foo {
2727

2828
fn oof(_: Foo) -> impl std::fmt::Debug {
2929
let mut bar = ham();
30-
let func = bar.next().unwrap();
30+
// Need to UFC invoke `Iterator::next`,
31+
// as otherwise the hidden type gets constrained to `&mut _`
32+
let func = Iterator::next(&mut bar).unwrap();
3133
return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type
3234
}
3335

tests/ui/impl-trait/issues/issue-70877.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: opaque type's hidden type cannot be another opaque type from the same scope
2-
--> $DIR/issue-70877.rs:31:12
2+
--> $DIR/issue-70877.rs:33:12
33
|
44
LL | return func(&"oof");
55
| ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error[E0599]: no method named `foo` found for struct `Bar` in the current scope
2+
--> $DIR/method-resolution.rs:22:11
3+
|
4+
LL | struct Bar<T>(T);
5+
| ------------- method `foo` not found for this struct
6+
...
7+
LL | x.foo();
8+
| ^^^ method not found in `Bar<impl Sized>`
9+
10+
error[E0391]: cycle detected when computing type of opaque `foo::{opaque#0}`
11+
--> $DIR/method-resolution.rs:18:24
12+
|
13+
LL | fn foo(x: bool) -> Bar<impl Sized> {
14+
| ^^^^^^^^^^
15+
|
16+
note: ...which requires type-checking `foo`...
17+
--> $DIR/method-resolution.rs:22:9
18+
|
19+
LL | x.foo();
20+
| ^
21+
= note: ...which requires evaluating trait selection obligation `Bar<foo::{opaque#0}>: core::marker::Unpin`...
22+
= note: ...which again requires computing type of opaque `foo::{opaque#0}`, completing the cycle
23+
note: cycle used when computing type of `foo::{opaque#0}`
24+
--> $DIR/method-resolution.rs:18:24
25+
|
26+
LL | fn foo(x: bool) -> Bar<impl Sized> {
27+
| ^^^^^^^^^^
28+
= 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
29+
30+
error: aborting due to 2 previous errors
31+
32+
Some errors have detailed explanations: E0391, E0599.
33+
For more information about an error, try `rustc --explain E0391`.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0599]: no method named `foo` found for struct `Bar` in the current scope
2+
--> $DIR/method-resolution.rs:22:11
3+
|
4+
LL | struct Bar<T>(T);
5+
| ------------- method `foo` not found for this struct
6+
...
7+
LL | x.foo();
8+
| ^^^ method not found in `Bar<_>`
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0599`.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//! Check that we do not constrain hidden types during method resolution.
2+
//! Otherwise we'd pick up that calling `bar` can be satisfied iff `u32`
3+
//! is the hidden type of the RPIT.
4+
5+
//@ revisions: current next
6+
//@[next] compile-flags: -Znext-solver
7+
8+
trait Trait {}
9+
10+
impl Trait for u32 {}
11+
12+
struct Bar<T>(T);
13+
14+
impl Bar<u32> {
15+
fn bar(self) {}
16+
}
17+
18+
fn foo(x: bool) -> Bar<impl Sized> {
19+
//[current]~^ ERROR: cycle
20+
if x {
21+
let x = foo(false);
22+
x.foo();
23+
//~^ ERROR: no method named `foo` found
24+
}
25+
todo!()
26+
}
27+
28+
fn main() {}

0 commit comments

Comments
 (0)