diff options
| author | bors <bors@rust-lang.org> | 2025-09-21 16:28:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-09-21 16:28:12 +0000 |
| commit | 7e4b8d702fedccc9c7803773a22c2e053ac3b004 (patch) | |
| tree | ae4e99039510dd23b4670854c09def488480a416 | |
| parent | 6710835ae739ca326441ff6c63d24fb123858300 (diff) | |
| parent | 3934fc9eb29061168327640ba7b9ca8f79ba01e2 (diff) | |
| download | rust-7e4b8d702fedccc9c7803773a22c2e053ac3b004.tar.gz rust-7e4b8d702fedccc9c7803773a22c2e053ac3b004.zip | |
Auto merge of #146659 - cjgillot:impossible-taint, r=oli-obk
Consider errors in MIR as impossible predicates to empty the body. The ICEs come from elaborating drops or performing state transform in MIR bodies that fail typeck or borrowck. If the body is tainted, replace it with `unreachable`. Fixes https://github.com/rust-lang/rust/issues/122630 Fixes https://github.com/rust-lang/rust/issues/122904 Fixes https://github.com/rust-lang/rust/issues/125185 Fixes https://github.com/rust-lang/rust/issues/139556
| -rw-r--r-- | compiler/rustc_mir_transform/src/impossible_predicates.rs | 33 | ||||
| -rw-r--r-- | tests/crashes/122904-2.rs | 17 | ||||
| -rw-r--r-- | tests/crashes/139556.rs | 13 | ||||
| -rw-r--r-- | tests/ui/consts/promoted_const_call2.rs | 1 | ||||
| -rw-r--r-- | tests/ui/consts/promoted_const_call2.stderr | 17 | ||||
| -rw-r--r-- | tests/ui/coroutine/moved-twice.rs (renamed from tests/crashes/122630.rs) | 11 | ||||
| -rw-r--r-- | tests/ui/coroutine/moved-twice.stderr | 24 | ||||
| -rw-r--r-- | tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs | 19 | ||||
| -rw-r--r-- | tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr | 30 | ||||
| -rw-r--r-- | tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs | 24 | ||||
| -rw-r--r-- | tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr | 58 | ||||
| -rw-r--r-- | tests/ui/type-alias-impl-trait/type-error-drop-elaboration.rs (renamed from tests/crashes/125185.rs) | 3 | ||||
| -rw-r--r-- | tests/ui/type-alias-impl-trait/type-error-drop-elaboration.stderr | 12 |
13 files changed, 201 insertions, 61 deletions
diff --git a/compiler/rustc_mir_transform/src/impossible_predicates.rs b/compiler/rustc_mir_transform/src/impossible_predicates.rs index b03518de00a..883ee32bdec 100644 --- a/compiler/rustc_mir_transform/src/impossible_predicates.rs +++ b/compiler/rustc_mir_transform/src/impossible_predicates.rs @@ -28,6 +28,7 @@ use rustc_middle::mir::{Body, START_BLOCK, TerminatorKind}; use rustc_middle::ty::{TyCtxt, TypeFlags, TypeVisitableExt}; +use rustc_span::def_id::DefId; use rustc_trait_selection::traits; use tracing::trace; @@ -35,23 +36,29 @@ use crate::pass_manager::MirPass; pub(crate) struct ImpossiblePredicates; +fn has_impossible_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx); + tracing::trace!(?predicates); + let predicates = predicates.predicates.into_iter().filter(|p| { + !p.has_type_flags( + // Only consider global clauses to simplify. + TypeFlags::HAS_FREE_LOCAL_NAMES + // Clauses that refer to unevaluated constants as they cause cycles. + | TypeFlags::HAS_CT_PROJECTION, + ) + }); + let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect(); + tracing::trace!(?predicates); + predicates.references_error() || traits::impossible_predicates(tcx, predicates) +} + impl<'tcx> MirPass<'tcx> for ImpossiblePredicates { #[tracing::instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { tracing::trace!(def_id = ?body.source.def_id()); - let predicates = tcx.predicates_of(body.source.def_id()).instantiate_identity(tcx); - tracing::trace!(?predicates); - let predicates = predicates.predicates.into_iter().filter(|p| { - !p.has_type_flags( - // Only consider global clauses to simplify. - TypeFlags::HAS_FREE_LOCAL_NAMES - // Clauses that refer to unevaluated constants as they cause cycles. - | TypeFlags::HAS_CT_PROJECTION, - ) - }); - let predicates: Vec<_> = traits::elaborate(tcx, predicates).collect(); - tracing::trace!(?predicates); - if predicates.references_error() || traits::impossible_predicates(tcx, predicates) { + let impossible = body.tainted_by_errors.is_some() + || has_impossible_predicates(tcx, body.source.def_id()); + if impossible { trace!("found unsatisfiable predicates"); // Clear the body to only contain a single `unreachable` statement. let bbs = body.basic_blocks.as_mut(); diff --git a/tests/crashes/122904-2.rs b/tests/crashes/122904-2.rs deleted file mode 100644 index db66b8625db..00000000000 --- a/tests/crashes/122904-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #122904 -trait T {} - -type Alias<'a> = impl T; - -struct S; -impl<'a> T for &'a S {} - -#[define_opaque(Alias)] -fn with_positive(fun: impl Fn(Alias<'_>)) { - with_positive(|&n| ()); -} - -#[define_opaque(Alias)] -fn main(Alias<'_>) { - with_positive(|&a| ()); -} diff --git a/tests/crashes/139556.rs b/tests/crashes/139556.rs deleted file mode 100644 index 60dc8d7c3af..00000000000 --- a/tests/crashes/139556.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #139556 - -trait T {} - -type Alias<'a> = impl T; - -struct S; -impl<'a> T for &'a S {} - -#[define_opaque(Alias)] -fn with_positive(fun: impl Fn(Alias<'_>)) { - with_positive(|&n| ()); -} diff --git a/tests/ui/consts/promoted_const_call2.rs b/tests/ui/consts/promoted_const_call2.rs index f332cd18cea..62391f098e5 100644 --- a/tests/ui/consts/promoted_const_call2.rs +++ b/tests/ui/consts/promoted_const_call2.rs @@ -4,7 +4,6 @@ pub const C: () = { let _: &'static _ = &id(&String::new()); //~^ ERROR: temporary value dropped while borrowed //~| ERROR: temporary value dropped while borrowed - //~| ERROR: destructor of `String` cannot be evaluated at compile-time }; fn main() { diff --git a/tests/ui/consts/promoted_const_call2.stderr b/tests/ui/consts/promoted_const_call2.stderr index bdb43385d20..e62458d1a6a 100644 --- a/tests/ui/consts/promoted_const_call2.stderr +++ b/tests/ui/consts/promoted_const_call2.stderr @@ -18,16 +18,8 @@ LL | let _: &'static _ = &id(&String::new()); | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` -error[E0493]: destructor of `String` cannot be evaluated at compile-time - --> $DIR/promoted_const_call2.rs:4:30 - | -LL | let _: &'static _ = &id(&String::new()); - | ^^^^^^^^^^^^^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constants - error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call2.rs:11:26 + --> $DIR/promoted_const_call2.rs:10:26 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -38,7 +30,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call2.rs:11:30 + --> $DIR/promoted_const_call2.rs:10:30 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement @@ -46,7 +38,6 @@ LL | let _: &'static _ = &id(&String::new()); | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0493, E0716. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/crashes/122630.rs b/tests/ui/coroutine/moved-twice.rs index e66624431c5..72b83e274c9 100644 --- a/tests/crashes/122630.rs +++ b/tests/ui/coroutine/moved-twice.rs @@ -1,22 +1,27 @@ -//@ known-bug: #122630 +//! Regression test for #122630 //@ compile-flags: -Zvalidate-mir +#![feature(coroutines, coroutine_trait, yield_expr)] + use std::ops::Coroutine; const FOO_SIZE: usize = 1024; struct Foo([u8; FOO_SIZE]); impl Drop for Foo { - fn move_before_yield_with_noop() -> impl Coroutine<Yield = ()> {} + fn drop(&mut self) {} } fn overlap_move_points() -> impl Coroutine<Yield = ()> { - static || { + #[coroutine] static || { let first = Foo([0; FOO_SIZE]); yield; let second = first; yield; let second = first; + //~^ ERROR: use of moved value: `first` [E0382] yield; } } + +fn main() {} diff --git a/tests/ui/coroutine/moved-twice.stderr b/tests/ui/coroutine/moved-twice.stderr new file mode 100644 index 00000000000..2b21f6c59f0 --- /dev/null +++ b/tests/ui/coroutine/moved-twice.stderr @@ -0,0 +1,24 @@ +error[E0382]: use of moved value: `first` + --> $DIR/moved-twice.rs:21:22 + | +LL | let first = Foo([0; FOO_SIZE]); + | ----- move occurs because `first` has type `Foo`, which does not implement the `Copy` trait +LL | yield; +LL | let second = first; + | ----- value moved here +LL | yield; +LL | let second = first; + | ^^^^^ value used here after move + | +note: if `Foo` implemented `Clone`, you could clone the value + --> $DIR/moved-twice.rs:9:1 + | +LL | struct Foo([u8; FOO_SIZE]); + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let second = first; + | ----- you could clone this value + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs new file mode 100644 index 00000000000..5541c5267f3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs @@ -0,0 +1,19 @@ +//! Regression test for ICE #139556 + +#![feature(type_alias_impl_trait)] + +trait T {} + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S {} + +#[define_opaque(Alias)] +fn with_positive(fun: impl Fn(Alias<'_>)) { +//~^ WARN: function cannot return without recursing + with_positive(|&n| ()); + //~^ ERROR: cannot move out of a shared reference +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr new file mode 100644 index 00000000000..e1fdd222ee1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr @@ -0,0 +1,30 @@ +warning: function cannot return without recursing + --> $DIR/recursive-drop-elaboration-2.rs:13:1 + | +LL | fn with_positive(fun: impl Fn(Alias<'_>)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | with_positive(|&n| ()); + | ---------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0507]: cannot move out of a shared reference + --> $DIR/recursive-drop-elaboration-2.rs:15:20 + | +LL | with_positive(|&n| ()); + | ^- + | | + | data moved here + | move occurs because `n` has type `S`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - with_positive(|&n| ()); +LL + with_positive(|n| ()); + | + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs new file mode 100644 index 00000000000..dd28732ebb2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs @@ -0,0 +1,24 @@ +//! Regression test for #122904. + +#![feature(type_alias_impl_trait)] + +trait T {} + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S {} + +#[define_opaque(Alias)] +fn with_positive(fun: impl Fn(Alias<'_>)) { +//~^ WARN: function cannot return without recursing + with_positive(|&n| ()); + //~^ ERROR: cannot move out of a shared reference +} + +#[define_opaque(Alias)] +fn main(_: Alias<'_>) { +//~^ ERROR: `main` function has wrong type [E0580] + with_positive(|&a| ()); + //~^ ERROR: cannot move out of a shared reference +} diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr new file mode 100644 index 00000000000..8b5dc950afd --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr @@ -0,0 +1,58 @@ +warning: function cannot return without recursing + --> $DIR/recursive-drop-elaboration.rs:13:1 + | +LL | fn with_positive(fun: impl Fn(Alias<'_>)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | with_positive(|&n| ()); + | ---------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0507]: cannot move out of a shared reference + --> $DIR/recursive-drop-elaboration.rs:15:20 + | +LL | with_positive(|&n| ()); + | ^- + | | + | data moved here + | move occurs because `n` has type `S`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - with_positive(|&n| ()); +LL + with_positive(|n| ()); + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/recursive-drop-elaboration.rs:22:20 + | +LL | with_positive(|&a| ()); + | ^- + | | + | data moved here + | move occurs because `a` has type `S`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - with_positive(|&a| ()); +LL + with_positive(|a| ()); + | + +error[E0580]: `main` function has wrong type + --> $DIR/recursive-drop-elaboration.rs:20:1 + | +LL | type Alias<'a> = impl T; + | ------ the found opaque type +... +LL | fn main(_: Alias<'_>) { + | ^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected signature `fn()` + found signature `for<'a> fn(Alias<'a>)` + +error: aborting due to 3 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0507, E0580. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/crashes/125185.rs b/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.rs index e77666ca73d..c0fb9007865 100644 --- a/tests/crashes/125185.rs +++ b/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.rs @@ -1,4 +1,4 @@ -//@ known-bug: rust-lang/rust#125185 +//! Regression test for #125185 //@ compile-flags: -Zvalidate-mir #![feature(type_alias_impl_trait)] @@ -10,6 +10,7 @@ struct A; #[define_opaque(Foo)] const fn foo() -> Foo { value() + //~^ ERROR: cannot find function `value` in this scope } const VALUE: Foo = foo(); diff --git a/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.stderr b/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.stderr new file mode 100644 index 00000000000..1cb33eabd90 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-error-drop-elaboration.stderr @@ -0,0 +1,12 @@ +error[E0425]: cannot find function `value` in this scope + --> $DIR/type-error-drop-elaboration.rs:12:5 + | +LL | value() + | ^^^^^ help: a constant with a similar name exists: `VALUE` +... +LL | const VALUE: Foo = foo(); + | ------------------------- similarly named constant `VALUE` defined here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. |
