diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 7318d02d24c..61898b06476 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1388,10 +1388,10 @@ fn inferred_kind( // 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(_) => { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 5dc341653e5..17aa43ae7c0 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -621,6 +621,16 @@ fn reset(&mut self) { 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 @@ -1443,7 +1453,8 @@ fn consider_probe( (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); @@ -1514,7 +1525,13 @@ fn consider_probe( { 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); @@ -1560,7 +1577,8 @@ fn consider_probe( (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); @@ -1603,7 +1621,7 @@ fn consider_probe( } 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; diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.rs b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.rs index e2fc2961a44..a33d4928f01 100644 --- a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.rs +++ b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.rs @@ -7,4 +7,5 @@ impl Fail { fn main() { Fail::<()>::C + //~^ ERROR no associated item named `C` found for struct `Fail<()>` in the current scope } diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.stderr b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.stderr index f0a6ccf243a..c5816393107 100644 --- a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.stderr +++ b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg.stderr @@ -7,6 +7,19 @@ LL | struct Fail; = 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; + | -------------- 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` -For more information about this error, try `rustc --explain E0392`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0599. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.rs b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.rs index cb53d902ba1..d891b7bd62b 100644 --- a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.rs +++ b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.rs @@ -14,4 +14,5 @@ impl Fail { fn main() { Fail::::C //~^ ERROR: type mismatch + //~| ERROR no associated item named `C` found for struct `Fail` in the current scope } diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.stderr b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.stderr index 0d63b7f5b29..18d458aea80 100644 --- a/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.stderr +++ b/tests/ui/associated-consts/wrong-projection-self-ty-invalid-bivariant-arg2.stderr @@ -1,3 +1,15 @@ +error[E0599]: no associated item named `C` found for struct `Fail` in the current scope + --> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:15:23 + | +LL | struct Fail, U>(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` + error[E0271]: type mismatch resolving `::Assoc == u32` --> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:15:5 | @@ -15,6 +27,7 @@ note: required by a bound in `Fail` LL | struct Fail, 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`. diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr deleted file mode 100644 index ef5633f7134..00000000000 --- a/tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0277]: the trait bound `(): std::error::Error` is not satisfied - --> $DIR/coerce-issue-49593-box-never.rs:18:5 - | -LL | Box::<_ /* ! */>::new(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` - | - = note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.rs b/tests/ui/coercion/coerce-issue-49593-box-never.rs index 53071be47dc..e5569592045 100644 --- a/tests/ui/coercion/coerce-issue-49593-box-never.rs +++ b/tests/ui/coercion/coerce-issue-49593-box-never.rs @@ -1,5 +1,5 @@ //@ revisions: nofallback fallback -//@check-fail +//@[fallback] check-pass #![feature(never_type)] #![cfg_attr(fallback, feature(never_type_fallback))] @@ -13,10 +13,10 @@ fn raw_ptr_box(t: T) -> *mut T { } fn foo(x: !) -> Box { - // 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 { diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr index 217f609459e..b88fe966b77 100644 --- a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -8,7 +8,7 @@ note: required by a const generic parameter in `Mask::::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 = Mask::<_, _>::splat(false); +LL | let y: Mask<_, N> = Mask::<_, _>::splat(false); | ++++++++++++ error[E0284]: type annotations needed for `Mask<_, _>` @@ -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 = Mask::<_, _>::splat(false); +LL | let y: Mask<_, N> = Mask::<_, _>::splat(false); | ++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-62742.rs b/tests/ui/impl-trait/issues/issue-62742.rs index 56c63a1daa8..c64278c2c5b 100644 --- a/tests/ui/impl-trait/issues/issue-62742.rs +++ b/tests/ui/impl-trait/issues/issue-62742.rs @@ -2,7 +2,8 @@ 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() { diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr index 7a1bcfc70d5..94822e41ccd 100644 --- a/tests/ui/impl-trait/issues/issue-62742.stderr +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -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(PhantomData); + | --------------------- doesn't satisfy `RawImpl<_>: Raw<_>` +... +LL | pub struct SafeImpl>(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> SafeImpl { + | ^^^^^^ -------------- + | | + | unsatisfied trait bound introduced here +note: the trait `Raw` must be implemented + --> $DIR/issue-62742.rs:19:1 + | +LL | pub trait Raw { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +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>(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 @@ -17,20 +49,20 @@ LL | pub struct SafeImpl>(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> SafeImpl { | ^^^^^^ -------------- | | | 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 { | ^^^^^^^^^^^^^^^^^^^^^^^^ 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<()>` @@ -38,12 +70,12 @@ LL | WrongImpl::<()>::foo(0i32); = 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>(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`. diff --git a/tests/ui/inference/need_type_info/type-alias-indirect.stderr b/tests/ui/inference/need_type_info/type-alias-indirect.stderr index 5c5b4c149c1..535c0044aec 100644 --- a/tests/ui/inference/need_type_info/type-alias-indirect.stderr +++ b/tests/ui/inference/need_type_info/type-alias-indirect.stderr @@ -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 diff --git a/tests/ui/inference/need_type_info/type-alias.stderr b/tests/ui/inference/need_type_info/type-alias.stderr index fd9bcf2fe3f..2c39a3f5646 100644 --- a/tests/ui/inference/need_type_info/type-alias.stderr +++ b/tests/ui/inference/need_type_info/type-alias.stderr @@ -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 diff --git a/tests/ui/methods/receiver-equality.rs b/tests/ui/methods/receiver-equality.rs new file mode 100644 index 00000000000..891435a425e --- /dev/null +++ b/tests/ui/methods/receiver-equality.rs @@ -0,0 +1,16 @@ +// Tests that we probe receivers invariantly when using path-based method lookup. + +struct B(T); + +impl B { + fn method(self) { + println!("hey"); + } +} + +fn foo(y: B) { + B:: fn(&'a ())>::method(y); + //~^ ERROR no function or associated item named `method` found +} + +fn main() {} diff --git a/tests/ui/methods/receiver-equality.stderr b/tests/ui/methods/receiver-equality.stderr new file mode 100644 index 00000000000..cea3340e386 --- /dev/null +++ b/tests/ui/methods/receiver-equality.stderr @@ -0,0 +1,12 @@ +error[E0599]: no function or associated item named `method` found for struct `B fn(&'a ())>` in the current scope + --> $DIR/receiver-equality.rs:12:30 + | +LL | struct B(T); + | ----------- function or associated item `method` not found for this struct +... +LL | B:: fn(&'a ())>::method(y); + | ^^^^^^ function or associated item not found in `B` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.rs b/tests/ui/suggestions/mut-borrow-needed-by-trait.rs index 924bfd82eb8..66e1e77c905 100644 --- a/tests/ui/suggestions/mut-borrow-needed-by-trait.rs +++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -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 } diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr index b2f9150142f..09a9b1d3b34 100644 --- a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -10,16 +10,6 @@ LL | let fp = BufWriter::new(fp); note: required by a bound in `BufWriter::::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 | @@ -31,13 +21,13 @@ 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(); | ^^ @@ -45,7 +35,7 @@ LL | writeln!(fp, "hello world").unwrap(); `&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`.