Skip to content

Commit

Permalink
Auto merge of #126128 - oli-obk:method_ice, r=lcnr
Browse files Browse the repository at this point in the history
Consistently use subtyping in method resolution

fixes #126062

An earlier version of this PR modified how we compute variance, but the root cause was an inconsistency between the usage of `eq` and `sub`, where we assumed that the latter passing implies the former will pass.

r? `@compiler-errors`
  • Loading branch information
bors committed Jun 17, 2024
2 parents 3baa20b + 3e6e6b1 commit 9b584a6
Show file tree
Hide file tree
Showing 16 changed files with 108 additions and 118 deletions.
9 changes: 3 additions & 6 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -750,16 +750,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

/// Resolves an associated value path into a base type and associated constant, or method
/// resolution. The newly resolved definition is written into `type_dependent_defs`.
#[instrument(level = "trace", skip(self), ret)]
pub fn resolve_ty_and_res_fully_qualified_call(
&self,
qpath: &'tcx QPath<'tcx>,
hir_id: HirId,
span: Span,
) -> (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
debug!(
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
qpath, hir_id, span
);
let (ty, qself, item_segment) = match *qpath {
QPath::Resolved(ref opt_qself, path) => {
return (
Expand Down Expand Up @@ -1417,10 +1414,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).eq(
match self.at(&self.misc(span), self.param_env).sub(
DefineOpaqueTypes::Yes,
impl_ty,
self_ty,
impl_ty,
) {
Ok(ok) => self.register_infer_ok_obligations(ok),
Err(_) => {
Expand Down
11 changes: 0 additions & 11 deletions tests/crashes/126062.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
struct Fail<T>;
//~^ ERROR: type parameter `T` is never used

impl Fail<i32> {
const C: () = ();
}

fn main() {
Fail::<()>::C
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0392]: type parameter `T` is never used
--> $DIR/wrong-projection-self-ty-invalid-bivariant-arg.rs:1:13
|
LL | struct Fail<T>;
| ^ unused type parameter
|
= 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

For more information about this error, try `rustc --explain E0392`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
trait Proj {
type Assoc;
}
impl<T> Proj for T {
type Assoc = T;
}

struct Fail<T: Proj<Assoc = U>, U>(T);

impl Fail<i32, i32> {
const C: () = ();
}

fn main() {
Fail::<i32, u32>::C
//~^ ERROR: type mismatch
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0271]: type mismatch resolving `<i32 as Proj>::Assoc == u32`
--> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:15:5
|
LL | Fail::<i32, u32>::C
| ^^^^^^^^^^^^^^^^ type mismatch resolving `<i32 as Proj>::Assoc == u32`
|
note: expected this to be `u32`
--> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:5:18
|
LL | type Assoc = T;
| ^
note: required by a bound in `Fail`
--> $DIR/wrong-projection-self-ty-invalid-bivariant-arg2.rs:8:21
|
LL | struct Fail<T: Proj<Assoc = U>, U>(T);
| ^^^^^^^^^ required by this bound in `Fail`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0271`.

This file was deleted.

58 changes: 0 additions & 58 deletions tests/ui/coercion/coerce-issue-49593-box-never-windows.rs

This file was deleted.

11 changes: 11 additions & 0 deletions tests/ui/coercion/coerce-issue-49593-box-never.fallback.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
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`.
12 changes: 6 additions & 6 deletions tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
error[E0277]: the trait bound `(): std::error::Error` is not satisfied
--> $DIR/coerce-issue-49593-box-never.rs:18:53
--> $DIR/coerce-issue-49593-box-never.rs:18:5
|
LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
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[E0277]: the trait bound `(): std::error::Error` is not satisfied
--> $DIR/coerce-issue-49593-box-never.rs:23:49
--> $DIR/coerce-issue-49593-box-never.rs:24:5
|
LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
LL | raw_ptr_box::<_ /* ! */>(x)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
|
= note: required for the cast from `*mut ()` to `*mut (dyn std::error::Error + 'static)`

Expand Down
20 changes: 10 additions & 10 deletions tests/ui/coercion/coerce-issue-49593-box-never.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//@ revisions: nofallback fallback
//@ ignore-windows - the number of `Error` impls is platform-dependent
//@[fallback] check-pass
//@[nofallback] check-fail
//@check-fail

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

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

fn foo_raw_ptr(x: !) -> *mut dyn Error {
/* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
/* *mut $0 is coerced to *mut Error here */
raw_ptr_box::<_ /* ! */>(x)
//[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied
}

fn no_coercion(d: *mut dyn Error) -> *mut dyn Error {
/* an unsize coercion won't compile here, and it is indeed not used
because there is nothing requiring the _ to be Sized */
because there is nothing requiring the _ to be Sized */
d as *mut _
}

Expand All @@ -49,10 +50,9 @@ fn foo_no_never() {
first_iter = true;
}

let mut y : Option<S> = None;
let mut y: Option<S> = None;
// assert types are equal
mem::swap(&mut x, &mut y);
}

fn main() {
}
fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ note: required by a bound 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 type for type parameter `T` is specified
|
LL | let y: Mask<_, N> = Mask::<_, _>::splat(false);
LL | let y: Mask<T, N> = Mask::<_, _>::splat(false);
| ++++++++++++

error: aborting due to 1 previous error
Expand Down
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`
| ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `DirectAlias`

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`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `DirectButWithDefaultAlias`

error: aborting due to 3 previous errors

Expand Down
1 change: 1 addition & 0 deletions tests/ui/suggestions/mut-borrow-needed-by-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ 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: 13 additions & 3 deletions tests/ui/suggestions/mut-borrow-needed-by-trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ 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 @@ -21,21 +31,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:21:14
--> $DIR/mut-borrow-needed-by-trait.rs:22: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:21:14
--> $DIR/mut-borrow-needed-by-trait.rs:22: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 3 previous errors
error: aborting due to 4 previous errors

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

0 comments on commit 9b584a6

Please sign in to comment.