about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-12-25 03:10:54 +0000
committerMichael Goulet <michael@errs.io>2025-01-22 19:13:52 +0000
commit72fa87445670046d64222980ec9988bf6975fc56 (patch)
treedc29021500b206050f29f8eb3d94cbe789f17e13
parentdee7d0e730a3a3ed98c89dd33c4ac16edc82de8a (diff)
downloadrust-72fa87445670046d64222980ec9988bf6975fc56.tar.gz
rust-72fa87445670046d64222980ec9988bf6975fc56.zip
Don't ICE in coerce when autoderef fails to structurally normalize non-WF type in new solver
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs14
-rw-r--r--tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs17
-rw-r--r--tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr39
3 files changed, 67 insertions, 3 deletions
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 6945dbc3216..720f51c0be6 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 `&<not well formed>`, 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 00000000000..d05def2cb75
--- /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 00000000000..32a7766a638
--- /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`.