about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJana Dönszelmann <jonathan@donsz.nl>2025-06-25 22:14:56 +0200
committerGitHub <noreply@github.com>2025-06-25 22:14:56 +0200
commitda42289cd75487d0f75cafd7bbcc39c18aec8f83 (patch)
treea27c0f68e0760ba574e9bc2842cf7a7d3c46284f
parent69b11c64ebf9798984f8ceb250cb1b755488aaf1 (diff)
parent1c9f7955d4cf126a75e21b0d643880dc429a466f (diff)
downloadrust-da42289cd75487d0f75cafd7bbcc39c18aec8f83.tar.gz
rust-da42289cd75487d0f75cafd7bbcc39c18aec8f83.zip
Rollup merge of #142976 - compiler-errors:coerce-ice, r=fee1-dead
Check CoerceUnsized impl validity before coercing

Self-explanatory from the title.

Fixes rust-lang/rust#126982
Fixes rust-lang/rust#131048
Fixes rust-lang/rust#134217
Fixes rust-lang/rust#126269
Fixes rust-lang/rust#138265
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs15
-rw-r--r--tests/crashes/126269.rs12
-rw-r--r--tests/crashes/126982.rs18
-rw-r--r--tests/crashes/131048.rs7
-rw-r--r--tests/crashes/134217.rs9
-rw-r--r--tests/crashes/138265.rs12
-rw-r--r--tests/ui/coercion/invalid-blanket-coerce-unsized-impl.rs13
-rw-r--r--tests/ui/coercion/invalid-blanket-coerce-unsized-impl.stderr19
8 files changed, 46 insertions, 59 deletions
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 24092c01125..0ce0bc313c7 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -46,7 +46,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_infer::infer::relate::RelateResult;
 use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
 use rustc_infer::traits::{
-    IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation,
+    IfExpressionCause, ImplSource, MatchExpressionArmCause, Obligation, PredicateObligation,
     PredicateObligations, SelectionError,
 };
 use rustc_middle::span_bug;
@@ -704,6 +704,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                     // be silent, as it causes a type mismatch later.
                 }
 
+                Ok(Some(ImplSource::UserDefined(impl_source))) => {
+                    queue.extend(impl_source.nested);
+                    // Certain incoherent `CoerceUnsized` implementations may cause ICEs,
+                    // so check the impl's validity. Taint the body so that we don't try
+                    // to evaluate these invalid coercions in CTFE. We only need to do this
+                    // for local impls, since upstream impls should be valid.
+                    if impl_source.impl_def_id.is_local()
+                        && let Err(guar) =
+                            self.tcx.ensure_ok().coerce_unsized_info(impl_source.impl_def_id)
+                    {
+                        self.fcx.set_tainted_by_errors(guar);
+                    }
+                }
                 Ok(Some(impl_source)) => queue.extend(impl_source.nested_obligations()),
             }
         }
diff --git a/tests/crashes/126269.rs b/tests/crashes/126269.rs
deleted file mode 100644
index ca4b76eb930..00000000000
--- a/tests/crashes/126269.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: rust-lang/rust#126269
-#![feature(coerce_unsized)]
-
-pub enum Foo<T> {
-    Bar([T; usize::MAX]),
-}
-
-use std::ops::CoerceUnsized;
-
-impl<T, U> CoerceUnsized<U> for T {}
-
-fn main() {}
diff --git a/tests/crashes/126982.rs b/tests/crashes/126982.rs
deleted file mode 100644
index 8522d9415eb..00000000000
--- a/tests/crashes/126982.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//@ known-bug: rust-lang/rust#126982
-
-#![feature(coerce_unsized)]
-use std::ops::CoerceUnsized;
-
-struct Foo<T: ?Sized> {
-    a: T,
-}
-
-impl<T, U> CoerceUnsized<U> for Foo<T> {}
-
-union U {
-    a: usize,
-}
-
-const C: U = Foo { a: 10 };
-
-fn main() {}
diff --git a/tests/crashes/131048.rs b/tests/crashes/131048.rs
deleted file mode 100644
index d57e9921a8a..00000000000
--- a/tests/crashes/131048.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ known-bug: #131048
-
-impl<A> std::ops::CoerceUnsized<A> for A {}
-
-fn main() {
-    format_args!("Hello, world!");
-}
diff --git a/tests/crashes/134217.rs b/tests/crashes/134217.rs
deleted file mode 100644
index 1b14c660e8b..00000000000
--- a/tests/crashes/134217.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: #134217
-
-impl<A> std::ops::CoerceUnsized<A> for A {}
-
-fn main() {
-    if let _ = true
-        && true
-    {}
-}
diff --git a/tests/crashes/138265.rs b/tests/crashes/138265.rs
deleted file mode 100644
index f6c8ea74889..00000000000
--- a/tests/crashes/138265.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: #138265
-
-#![feature(coerce_unsized)]
-#![crate_type = "lib"]
-impl<A> std::ops::CoerceUnsized<A> for A {}
-pub fn f() {
-    [0; {
-        let mut c = &0;
-        c = &0;
-        0
-    }]
-}
diff --git a/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.rs b/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.rs
new file mode 100644
index 00000000000..a4fd7710718
--- /dev/null
+++ b/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.rs
@@ -0,0 +1,13 @@
+// Regression test minimized from #126982.
+// We used to apply a coerce_unsized coercion to literally every argument since
+// the blanket applied in literally all cases, even though it was incoherent.
+
+#![feature(coerce_unsized)]
+
+impl<A> std::ops::CoerceUnsized<A> for A {}
+//~^ ERROR type parameter `A` must be used as the type parameter for some local type
+//~| ERROR the trait `CoerceUnsized` may only be implemented for a coercion between structures
+
+const C: usize = 1;
+
+fn main() {}
diff --git a/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.stderr b/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.stderr
new file mode 100644
index 00000000000..377906ee334
--- /dev/null
+++ b/tests/ui/coercion/invalid-blanket-coerce-unsized-impl.stderr
@@ -0,0 +1,19 @@
+error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`)
+  --> $DIR/invalid-blanket-coerce-unsized-impl.rs:7:6
+   |
+LL | impl<A> std::ops::CoerceUnsized<A> for A {}
+   |      ^ type parameter `A` must be used as the type parameter for some local type
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error[E0377]: the trait `CoerceUnsized` may only be implemented for a coercion between structures
+  --> $DIR/invalid-blanket-coerce-unsized-impl.rs:7:1
+   |
+LL | impl<A> std::ops::CoerceUnsized<A> for A {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0210, E0377.
+For more information about an error, try `rustc --explain E0210`.