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 /compiler | |
| 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
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_mir_transform/src/impossible_predicates.rs | 33 |
1 files changed, 20 insertions, 13 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(); |
