diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 24092c01125fc..0ce0bc313c770 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 ca4b76eb930d1..0000000000000 --- a/tests/crashes/126269.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: rust-lang/rust#126269 -#![feature(coerce_unsized)] - -pub enum Foo { - Bar([T; usize::MAX]), -} - -use std::ops::CoerceUnsized; - -impl CoerceUnsized for T {} - -fn main() {} diff --git a/tests/crashes/126982.rs b/tests/crashes/126982.rs deleted file mode 100644 index 8522d9415eb88..0000000000000 --- 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 { - a: T, -} - -impl CoerceUnsized for Foo {} - -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 d57e9921a8ab5..0000000000000 --- a/tests/crashes/131048.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #131048 - -impl std::ops::CoerceUnsized 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 1b14c660e8b4c..0000000000000 --- a/tests/crashes/134217.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #134217 - -impl std::ops::CoerceUnsized 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 f6c8ea748895c..0000000000000 --- a/tests/crashes/138265.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #138265 - -#![feature(coerce_unsized)] -#![crate_type = "lib"] -impl std::ops::CoerceUnsized 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 0000000000000..a4fd771071887 --- /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 std::ops::CoerceUnsized 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 0000000000000..377906ee334a9 --- /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`) + --> $DIR/invalid-blanket-coerce-unsized-impl.rs:7:6 + | +LL | impl std::ops::CoerceUnsized 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 std::ops::CoerceUnsized 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`.