From 72fa87445670046d64222980ec9988bf6975fc56 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 25 Dec 2024 03:10:54 +0000 Subject: [PATCH] Don't ICE in coerce when autoderef fails to structurally normalize non-WF type in new solver --- compiler/rustc_hir_typeck/src/coercion.rs | 14 +++++-- .../next-solver/non-wf-in-coerce-pointers.rs | 17 ++++++++ .../non-wf-in-coerce-pointers.stderr | 39 +++++++++++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs create mode 100644 tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 6945dbc321697..720f51c0be6f7 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -461,9 +461,17 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // to the target type), since that should be the least // confusing. let Some(InferOk { value: ty, mut obligations }) = found else { - let err = first_error.expect("coerce_borrowed_pointer had no error"); - debug!("coerce_borrowed_pointer: failed with err = {:?}", err); - return Err(err); + if let Some(first_error) = first_error { + debug!("coerce_borrowed_pointer: failed with err = {:?}", first_error); + return Err(first_error); + } else { + // This may happen in the new trait solver since autoderef requires + // the pointee to be structurally normalizable, or else it'll just bail. + // So when we have a type like `&`, then we get no + // autoderef steps (even though there should be at least one). That means + // we get no type mismatches, since the loop above just exits early. + return Err(TypeError::Mismatch); + } }; if ty == a && mt_a.mutbl.is_not() && autoderef.step_count() == 1 { diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs new file mode 100644 index 0000000000000..d05def2cb757d --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Znext-solver + +trait Wf { + type Assoc; +} + +struct S { + f: &'static <() as Wf>::Assoc, + //~^ ERROR the trait bound `(): Wf` is not satisfied +} + +fn main() { + let x: S = todo!(); + let y: &() = x.f; + //~^ ERROR mismatched types + //~| ERROR the trait bound `(): Wf` is not satisfied +} diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr new file mode 100644 index 0000000000000..32a7766a638da --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr @@ -0,0 +1,39 @@ +error[E0277]: the trait bound `(): Wf` is not satisfied + --> $DIR/non-wf-in-coerce-pointers.rs:8:17 + | +LL | f: &'static <() as Wf>::Assoc, + | ^^^^^^^^^^^^^^^^^ the trait `Wf` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/non-wf-in-coerce-pointers.rs:3:1 + | +LL | trait Wf { + | ^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/non-wf-in-coerce-pointers.rs:14:18 + | +LL | let y: &() = x.f; + | --- ^^^ types differ + | | + | expected due to this + | + = note: expected reference `&()` + found reference `&'static <() as Wf>::Assoc` + +error[E0277]: the trait bound `(): Wf` is not satisfied + --> $DIR/non-wf-in-coerce-pointers.rs:14:18 + | +LL | let y: &() = x.f; + | ^^^ the trait `Wf` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/non-wf-in-coerce-pointers.rs:3:1 + | +LL | trait Wf { + | ^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`.