Skip to content

Commit

Permalink
Auto merge of rust-lang#123962 - oli-obk:define_opaque_types5, r=<try>
Browse files Browse the repository at this point in the history
Method resolution constrains hidden types instead of rejecting method candidates

Some of these are in probes and may affect inference.

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!()
}
```

r? `@compiler-errors`
  • Loading branch information
bors committed Apr 15, 2024
2 parents 5dcb678 + a6c6b29 commit e8b955c
Show file tree
Hide file tree
Showing 16 changed files with 194 additions and 57 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1448,7 +1448,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,
) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,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);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1488,7 +1488,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.probe(|_| {
// First check that the self type can be related.
let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env).sup(
DefineOpaqueTypes::No,
DefineOpaqueTypes::Yes,
probe.xform_self_ty,
self_ty,
) {
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/impl-trait/issues/issue-70877.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ fn ham() -> Foo {

fn oof(_: Foo) -> impl std::fmt::Debug {
let mut bar = ham();
let func = bar.next().unwrap();
return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type
let func = bar.next().unwrap(); //~ ERROR: type annotations needed
return func(&"oof");
}

fn main() {
Expand Down
21 changes: 9 additions & 12 deletions tests/ui/impl-trait/issues/issue-70877.stderr
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
error: opaque type's hidden type cannot be another opaque type from the same scope
--> $DIR/issue-70877.rs:31:12
error[E0282]: type annotations needed
--> $DIR/issue-70877.rs:30:9
|
LL | let func = bar.next().unwrap();
| ^^^^
LL | return func(&"oof");
| ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope
| ------------ type must be known at this point
|
note: opaque type whose hidden type is being assigned
--> $DIR/issue-70877.rs:28:19
help: consider giving `func` an explicit type
|
LL | fn oof(_: Foo) -> impl std::fmt::Debug {
| ^^^^^^^^^^^^^^^^^^^^
note: opaque type being used as hidden type
--> $DIR/issue-70877.rs:4:15
|
LL | type FooRet = impl std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^
LL | let func: /* Type */ = bar.next().unwrap();
| ++++++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0282`.
21 changes: 21 additions & 0 deletions tests/ui/impl-trait/method-resolution.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ check-pass

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();
}
todo!()
}

fn main() {}
6 changes: 3 additions & 3 deletions tests/ui/methods/opaque_param_in_ufc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#![feature(type_alias_impl_trait)]

//@ check-pass

struct Foo<T>(T);

impl Foo<u32> {
Expand All @@ -15,14 +18,11 @@ fn bar() -> Bar {
impl Foo<Bar> {
fn foo() -> Bar {
Self::method();
//~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
Foo::<Bar>::method();
//~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
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<Bar>`
todo!()
}
}
Expand Down
36 changes: 0 additions & 36 deletions tests/ui/methods/opaque_param_in_ufc.stderr

This file was deleted.

22 changes: 22 additions & 0 deletions tests/ui/type-alias-impl-trait/method_resolution.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#![feature(type_alias_impl_trait)]

type Foo = impl Sized;

struct Bar<T>(T);

impl Bar<Foo> {
fn bar(self) {}
}

impl Bar<u32> {
fn foo(self) {
self.bar()
//~^ ERROR: no method named `bar`
}
}

fn foo() -> Foo {
42_u32
}

fn main() {}
15 changes: 15 additions & 0 deletions tests/ui/type-alias-impl-trait/method_resolution.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
--> $DIR/method_resolution.rs:13:14
|
LL | struct Bar<T>(T);
| ------------- method `bar` not found for this struct
...
LL | self.bar()
| ^^^ method not found in `Bar<u32>`
|
= note: the method was found for
- `Bar<Foo>`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0599`.
22 changes: 22 additions & 0 deletions tests/ui/type-alias-impl-trait/method_resolution2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#![feature(type_alias_impl_trait)]
//@ check-pass

type Foo = impl Sized;

struct Bar<T>(T);

impl Bar<Foo> {
fn bar(self) {
self.foo()
}
}

impl Bar<u32> {
fn foo(self) {}
}

fn foo() -> Foo {
42_u32
}

fn main() {}
27 changes: 27 additions & 0 deletions tests/ui/type-alias-impl-trait/method_resolution3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#![feature(type_alias_impl_trait, arbitrary_self_types)]

type Foo = impl Copy;

#[derive(Copy, Clone)]
struct Bar<T>(T);

impl Bar<Foo> {
fn bar(self: Bar<u32>) {
//~^ ERROR: invalid `self` parameter
self.foo()
}
fn baz(self: &Bar<u32>) {
//~^ ERROR: invalid `self` parameter
self.foo()
}
}

impl Bar<u32> {
fn foo(self) {}
}

fn foo() -> Foo {
42_u32
}

fn main() {}
21 changes: 21 additions & 0 deletions tests/ui/type-alias-impl-trait/method_resolution3.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0307]: invalid `self` parameter type: Bar<u32>
--> $DIR/method_resolution3.rs:9:18
|
LL | fn bar(self: Bar<u32>) {
| ^^^^^^^^
|
= 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>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)

error[E0307]: invalid `self` parameter type: &Bar<u32>
--> $DIR/method_resolution3.rs:13:18
|
LL | fn baz(self: &Bar<u32>) {
| ^^^^^^^^^
|
= 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>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (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`.
27 changes: 27 additions & 0 deletions tests/ui/type-alias-impl-trait/method_resolution4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#![feature(type_alias_impl_trait, arbitrary_self_types)]

type Foo = impl Copy;

#[derive(Copy, Clone)]
struct Bar<T>(T);

impl Bar<Foo> {
fn bar(self) {}
}

impl Bar<u32> {
fn foo(self: Bar<Foo>) {
//~^ ERROR: invalid `self` parameter
self.bar()
}
fn foomp(self: &Bar<Foo>) {
//~^ ERROR: invalid `self` parameter
self.bar()
}
}

fn foo() -> Foo {
42_u32
}

fn main() {}
21 changes: 21 additions & 0 deletions tests/ui/type-alias-impl-trait/method_resolution4.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0307]: invalid `self` parameter type: Bar<Foo>
--> $DIR/method_resolution4.rs:13:18
|
LL | fn foo(self: Bar<Foo>) {
| ^^^^^^^^
|
= 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>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)

error[E0307]: invalid `self` parameter type: &Bar<Foo>
--> $DIR/method_resolution4.rs:17:20
|
LL | fn foomp(self: &Bar<Foo>) {
| ^^^^^^^^^
|
= 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>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (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`.

0 comments on commit e8b955c

Please sign in to comment.