Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relate receiver invariantly in method probe for Mode::Path #129073

Merged
merged 1 commit into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1388,10 +1388,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// This also occurs for an enum variant on a type alias.
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).sub(
match self.at(&self.misc(span), self.param_env).eq(
DefineOpaqueTypes::Yes,
self_ty,
impl_ty,
self_ty,
) {
Ok(ok) => self.register_infer_ok_obligations(ok),
Err(_) => {
Expand Down
26 changes: 22 additions & 4 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.unsatisfied_predicates.borrow_mut().clear();
}

/// When we're looking up a method by path (UFCS), we relate the receiver
/// types invariantly. When we are looking up a method by the `.` operator,
/// we relate them covariantly.
fn variance(&self) -> ty::Variance {
match self.mode {
Mode::MethodCall => ty::Covariant,
Mode::Path => ty::Invariant,
}
}

///////////////////////////////////////////////////////////////////////////
// CANDIDATE ASSEMBLY

Expand Down Expand Up @@ -1443,7 +1453,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);
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
match ocx.relate(cause, self.param_env, self.variance(), self_ty, xform_self_ty)
{
Ok(()) => {}
Err(err) => {
debug!("--> cannot relate self-types {:?}", err);
Expand Down Expand Up @@ -1514,7 +1525,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
{
return ProbeResult::NoMatch;
}
_ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
_ => match ocx.relate(
cause,
self.param_env,
self.variance(),
self_ty,
xform_self_ty,
) {
Ok(()) => {}
Err(err) => {
debug!("--> cannot relate self-types {:?}", err);
Expand Down Expand Up @@ -1560,7 +1577,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);
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
match ocx.relate(cause, self.param_env, self.variance(), self_ty, xform_self_ty)
{
Ok(()) => {}
Err(err) => {
debug!("--> cannot relate self-types {:?}", err);
Expand Down Expand Up @@ -1603,7 +1621,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}

debug!("comparing return_ty {:?} with xform ret ty {:?}", return_ty, xform_ret_ty);
match ocx.sup(cause, self.param_env, return_ty, xform_ret_ty) {
match ocx.relate(cause, self.param_env, self.variance(), xform_ret_ty, return_ty) {
Ok(()) => {}
Err(_) => {
result = ProbeResult::BadReturnType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ impl Fail<i32> {

fn main() {
Fail::<()>::C
//~^ ERROR no associated item named `C` found for struct `Fail<()>` in the current scope
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ LL | struct Fail<T>;
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead

error: aborting due to 1 previous error
error[E0599]: no associated item named `C` found for struct `Fail<()>` in the current scope
--> $DIR/wrong-projection-self-ty-invalid-bivariant-arg.rs:9:17
|
LL | struct Fail<T>;
| -------------- associated item `C` not found for this struct
...
LL | Fail::<()>::C
| ^ associated item not found in `Fail<()>`
|
= note: the associated item was found for
- `Fail<i32>`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0392`.
Some errors have detailed explanations: E0392, E0599.
For more information about an error, try `rustc --explain E0392`.
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ impl Fail<i32, i32> {
fn main() {
Fail::<i32, u32>::C
//~^ ERROR: type mismatch
//~| ERROR no associated item named `C` found for struct `Fail<i32, u32>` in the current scope
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
error[E0599]: no associated item named `C` found for struct `Fail<i32, u32>` in the current scope
--> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:15:23
|
LL | struct Fail<T: Proj<Assoc = U>, U>(T);
| ---------------------------------- associated item `C` not found for this struct
...
LL | Fail::<i32, u32>::C
| ^ associated item not found in `Fail<i32, u32>`
|
= note: the associated item was found for
- `Fail<i32, i32>`

error[E0271]: type mismatch resolving `<i32 as Proj>::Assoc == u32`
--> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:15:5
|
Expand All @@ -15,6 +27,7 @@ note: required by a bound in `Fail`
LL | struct Fail<T: Proj<Assoc = U>, U>(T);
| ^^^^^^^^^ required by this bound in `Fail`

error: aborting due to 1 previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0271`.
Some errors have detailed explanations: E0271, E0599.
For more information about an error, try `rustc --explain E0271`.
11 changes: 0 additions & 11 deletions tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr

This file was deleted.

8 changes: 4 additions & 4 deletions tests/ui/coercion/coerce-issue-49593-box-never.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@ revisions: nofallback fallback
//@check-fail
//@[fallback] check-pass

#![feature(never_type)]
#![cfg_attr(fallback, feature(never_type_fallback))]
Expand All @@ -13,10 +13,10 @@ fn raw_ptr_box<T>(t: T) -> *mut T {
}

fn foo(x: !) -> Box<dyn Error> {
// Subtyping during method resolution will generate new inference vars and
// subtype them. Thus fallback will not fall back to `!`, but `()` instead.
// Method resolution will generate new inference vars and relate them.
// Thus fallback will not fall back to `!`, but `()` instead.
Box::<_ /* ! */>::new(x)
//~^ ERROR trait bound `(): std::error::Error` is not satisfied
//[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied
}

fn foo_raw_ptr(x: !) -> *mut dyn Error {
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ note: required by a const generic parameter in `Mask::<T, N>::splat`
--> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
help: consider giving `y` an explicit type, where the value of const parameter `N` is specified
|
LL | let y: Mask<T, N> = Mask::<_, _>::splat(false);
LL | let y: Mask<_, N> = Mask::<_, _>::splat(false);
| ++++++++++++

error[E0284]: type annotations needed for `Mask<_, _>`
Expand All @@ -21,7 +21,7 @@ note: required by a const generic parameter in `Mask`
--> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
help: consider giving `y` an explicit type, where the value of const parameter `N` is specified
|
LL | let y: Mask<T, N> = Mask::<_, _>::splat(false);
LL | let y: Mask<_, N> = Mask::<_, _>::splat(false);
| ++++++++++++

error: aborting due to 2 previous errors
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/impl-trait/issues/issue-62742.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::marker::PhantomData;

fn a() {
WrongImpl::foo(0i32);
//~^ ERROR overflow assigning `_` to `[_]`
//~^ ERROR the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied
//~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
}

fn b() {
Expand Down
52 changes: 42 additions & 10 deletions tests/ui/impl-trait/issues/issue-62742.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
error[E0275]: overflow assigning `_` to `[_]`
error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied
--> $DIR/issue-62742.rs:4:16
|
LL | WrongImpl::foo(0i32);
| ^^^
| ^^^ function or associated item cannot be called on `SafeImpl<_, RawImpl<_>>` due to unsatisfied trait bounds
...
LL | pub struct RawImpl<T>(PhantomData<T>);
| --------------------- doesn't satisfy `RawImpl<_>: Raw<_>`
...
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
| ----------------------------------------- function or associated item `foo` not found for this struct
|
note: trait bound `RawImpl<_>: Raw<_>` was not satisfied
--> $DIR/issue-62742.rs:35:20
|
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
| ^^^^^^ --------------
| |
| unsatisfied trait bound introduced here
note: the trait `Raw` must be implemented
--> $DIR/issue-62742.rs:19:1
|
LL | pub trait Raw<T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
--> $DIR/issue-62742.rs:4:5
|
LL | WrongImpl::foo(0i32);
| ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
note: required by a bound in `SafeImpl`
--> $DIR/issue-62742.rs:33:35
|
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
| ^^^^^^ required by this bound in `SafeImpl`

error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
--> $DIR/issue-62742.rs:9:22
--> $DIR/issue-62742.rs:10:22
|
LL | WrongImpl::<()>::foo(0i32);
| ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds
Expand All @@ -17,33 +49,33 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
| ----------------------------------------- function or associated item `foo` not found for this struct
|
note: trait bound `RawImpl<()>: Raw<()>` was not satisfied
--> $DIR/issue-62742.rs:34:20
--> $DIR/issue-62742.rs:35:20
|
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
| ^^^^^^ --------------
| |
| unsatisfied trait bound introduced here
note: the trait `Raw` must be implemented
--> $DIR/issue-62742.rs:18:1
--> $DIR/issue-62742.rs:19:1
|
LL | pub trait Raw<T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
--> $DIR/issue-62742.rs:9:5
--> $DIR/issue-62742.rs:10:5
|
LL | WrongImpl::<()>::foo(0i32);
| ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
|
= help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
= help: for that trait implementation, expected `[()]`, found `()`
note: required by a bound in `SafeImpl`
--> $DIR/issue-62742.rs:32:35
--> $DIR/issue-62742.rs:33:35
|
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
| ^^^^^^ required by this bound in `SafeImpl`

error: aborting due to 3 previous errors
error: aborting due to 4 previous errors

Some errors have detailed explanations: E0275, E0277, E0599.
For more information about an error, try `rustc --explain E0275`.
Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/type-alias-indirect.rs:14:5
|
LL | IndirectAlias::new();
| ^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias`
| ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias`

error: aborting due to 1 previous error

Expand Down
6 changes: 3 additions & 3 deletions tests/ui/inference/need_type_info/type-alias.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ error[E0282]: type annotations needed
--> $DIR/type-alias.rs:12:5
|
LL | DirectAlias::new()
| ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `DirectAlias`
| ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`

error[E0282]: type annotations needed
--> $DIR/type-alias.rs:18:5
|
LL | IndirectAlias::new();
| ^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias`
| ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias`

error[E0282]: type annotations needed
--> $DIR/type-alias.rs:32:5
|
LL | DirectButWithDefaultAlias::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `DirectButWithDefaultAlias`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`

error: aborting due to 3 previous errors

Expand Down
16 changes: 16 additions & 0 deletions tests/ui/methods/receiver-equality.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Tests that we probe receivers invariantly when using path-based method lookup.

struct B<T>(T);

impl B<fn(&'static ())> {
fn method(self) {
println!("hey");
}
}

fn foo(y: B<fn(&'static ())>) {
B::<for<'a> fn(&'a ())>::method(y);
//~^ ERROR no function or associated item named `method` found
}

fn main() {}
12 changes: 12 additions & 0 deletions tests/ui/methods/receiver-equality.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0599]: no function or associated item named `method` found for struct `B<for<'a> fn(&'a ())>` in the current scope
--> $DIR/receiver-equality.rs:12:30
|
LL | struct B<T>(T);
| ----------- function or associated item `method` not found for this struct
...
LL | B::<for<'a> fn(&'a ())>::method(y);
| ^^^^^^ function or associated item not found in `B<fn(&())>`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0599`.
1 change: 0 additions & 1 deletion tests/ui/suggestions/mut-borrow-needed-by-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ fn main() {
let fp = BufWriter::new(fp);
//~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
//~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
//~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied

writeln!(fp, "hello world").unwrap(); //~ ERROR the method
}
16 changes: 3 additions & 13 deletions tests/ui/suggestions/mut-borrow-needed-by-trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,6 @@ LL | let fp = BufWriter::new(fp);
note: required by a bound in `BufWriter::<W>::new`
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL

error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
--> $DIR/mut-borrow-needed-by-trait.rs:17:14
|
LL | let fp = BufWriter::new(fp);
| ^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
|
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
note: required by a bound in `BufWriter`
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL

error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
--> $DIR/mut-borrow-needed-by-trait.rs:17:14
|
Expand All @@ -31,21 +21,21 @@ note: required by a bound in `BufWriter`
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL

error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied
--> $DIR/mut-borrow-needed-by-trait.rs:22:14
--> $DIR/mut-borrow-needed-by-trait.rs:21:14
|
LL | writeln!(fp, "hello world").unwrap();
| ---------^^---------------- method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
|
note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
--> $DIR/mut-borrow-needed-by-trait.rs:22:14
--> $DIR/mut-borrow-needed-by-trait.rs:21:14
|
LL | writeln!(fp, "hello world").unwrap();
| ^^
= note: the following trait bounds were not satisfied:
`&dyn std::io::Write: std::io::Write`
which is required by `BufWriter<&dyn std::io::Write>: std::io::Write`

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
Loading