mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
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
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
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 @@ fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceRe
|
||||
// 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()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {}
|
||||
@@ -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() {}
|
||||
@@ -1,7 +0,0 @@
|
||||
//@ known-bug: #131048
|
||||
|
||||
impl<A> std::ops::CoerceUnsized<A> for A {}
|
||||
|
||||
fn main() {
|
||||
format_args!("Hello, world!");
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
//@ known-bug: #134217
|
||||
|
||||
impl<A> std::ops::CoerceUnsized<A> for A {}
|
||||
|
||||
fn main() {
|
||||
if let _ = true
|
||||
&& true
|
||||
{}
|
||||
}
|
||||
@@ -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
|
||||
}]
|
||||
}
|
||||
@@ -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() {}
|
||||
@@ -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`.
|
||||
Reference in New Issue
Block a user