From 9549f82da01f238f91a4a53454706093e4ddcdc8 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Sat, 10 Oct 2026 14:53:01 +0800 Subject: [PATCH] fix correspondence between typing mode and mir phase --- compiler/rustc_middle/src/mir/mod.rs | 33 ++++++++----------- .../src/add_moves_for_packed_drops.rs | 6 ++-- .../src/elaborate_drops.rs | 4 +-- .../src/known_panics_lint.rs | 4 +-- compiler/rustc_mir_transform/src/lib.rs | 6 ++-- .../rustc_mir_transform/src/pass_manager.rs | 12 ++++--- .../src/post_analysis_normalize.rs | 4 +-- compiler/rustc_mir_transform/src/shim.rs | 2 ++ 8 files changed, 33 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index ebcc2da09551e..a4e8abc9ac163 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -415,37 +415,32 @@ impl<'tcx> Body<'tcx> { pub fn typing_env(&self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> { if tcx.use_typing_mode_post_typeck_through_borrowck() { match self.phase { - MirPhase::Built | MirPhase::Analysis(AnalysisPhase::Initial) - if let Some(def_id) = self.source.def_id().as_local() => - { + // `analysis_cleanup_passes` should use `PostBorrowck`, but doing so would + // complicate the code, and none of those passes seems to care. + MirPhase::Built | MirPhase::Analysis(AnalysisPhase::Initial) => { + let local_def_id = self + .source + .def_id() + .as_local() + .expect("We only build MIR for local bodies"); TypingEnv::new( tcx.param_env(self.source.def_id()), - ty::TypingMode::borrowck(tcx, def_id), + ty::TypingMode::borrowck(tcx, local_def_id), ) } - MirPhase::Analysis(AnalysisPhase::PostCleanup) - if let Some(def_id) = self.source.def_id().as_local() => - { - TypingEnv::new( - tcx.param_env(self.source.def_id()), - ty::TypingMode::post_borrowck_analysis(tcx, def_id), - ) - } - MirPhase::Built | MirPhase::Analysis(_) => { - // This branch happens for drop glue and fn ptr shims. - // FIXME: why do we do any of this analysis on drop glue etc? - // This should ideally all be skipped. + MirPhase::Analysis(AnalysisPhase::PostCleanup) | MirPhase::Runtime(_) => { TypingEnv::post_analysis(tcx, self.source.def_id()) } - MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()), } } else { match self.phase { - MirPhase::Built | MirPhase::Analysis(_) => TypingEnv::new( + MirPhase::Built | MirPhase::Analysis(AnalysisPhase::Initial) => TypingEnv::new( tcx.param_env(self.source.def_id()), ty::TypingMode::non_body_analysis(), ), - MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()), + MirPhase::Analysis(AnalysisPhase::PostCleanup) | MirPhase::Runtime(_) => { + TypingEnv::post_analysis(tcx, self.source.def_id()) + } } } } diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 41c63d4857df8..1b688d261a6ef 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::*; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::TyCtxt; use tracing::debug; use crate::patch::MirPatch; @@ -41,9 +41,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span); let mut patch = MirPatch::new(body); - // FIXME(#132279): This is used during the phase transition from analysis - // to runtime, so we have to manually specify the correct typing mode. - let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); + let typing_env = body.typing_env(tcx); for (bb, data) in body.basic_blocks.iter_enumerated() { let loc = Location { block: bb, statement_index: data.statements.len() }; diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index a1acc308506c2..acbba72d01e48 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -52,9 +52,7 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); - // FIXME(#132279): This is used during the phase transition from analysis - // to runtime, so we have to manually specify the correct typing mode. - let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); + let typing_env = body.typing_env(tcx); // For types that do not need dropping, the behaviour is trivial. So we only need to track // init/uninit for types that do need dropping. let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env)); diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index f448371977068..6422ddc5fa393 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -181,9 +181,7 @@ impl<'tcx> ty::layout::HasTypingEnv<'tcx> for ConstPropagator<'_, 'tcx> { impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> { let def_id = body.source.def_id(); - // FIXME(#132279): This is used during the phase transition from analysis - // to runtime, so we have to manually specify the correct typing mode. - let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); + let typing_env = body.typing_env(tcx); let can_const_prop = CanConstProp::check(tcx, typing_env, body); let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env, DummyMachine); diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index d73d9a82f1a22..4b1c223c82dcc 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -647,6 +647,10 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { ]; pm::run_passes(tcx, body, passes, Some(MirPhase::Analysis(AnalysisPhase::PostCleanup))); + // `PostAnalysisNormalize` is the pass that puts a body into `TypingMode::PostAnalysis`. + // It has to be run here because moving it earlier or later would cause `validate-mir` + // to fail due to mismatched typing envs. + pm::run_passes(tcx, body, &[&post_analysis_normalize::PostAnalysisNormalize], None); } /// Returns the sequence of passes that lowers analysis to runtime MIR. @@ -654,8 +658,6 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let passes: &[&dyn MirPass<'tcx>] = &[ // These next passes must be executed together. &add_call_guards::CriticalCallEdges, - // Must be done before drop elaboration because we need to drop opaque types, too. - &post_analysis_normalize::PostAnalysisNormalize, // Calling this after `PostAnalysisNormalize` ensures that we don't deal with opaque types. &add_subtyping_projections::Subtyper, &elaborate_drops::ElaborateDrops, diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index f3f65a070e500..3e76267356ee3 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -5,7 +5,7 @@ use std::sync::atomic::Ordering; use rustc_attr_ir::OptimizeAttr; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_hir::def_id::DefId; -use rustc_middle::mir::{Body, MirDumper, MirPhase, RuntimePhase}; +use rustc_middle::mir::{AnalysisPhase, Body, MirDumper, MirPhase, RuntimePhase}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::OptLevel; @@ -393,9 +393,13 @@ fn run_passes_inner<'tcx>( dump_mir_for_phase_change(tcx, body); - let validate = - (validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip()) - || new_phase == MirPhase::Runtime(RuntimePhase::Optimized); + let validate = (validate_each + && tcx.sess.opts.unstable_opts.validate_mir + && !body.should_skip() + // Skip validating the body in `TypingMode::PostAnalysis` because we haven't + // revealed opaques yet. + && (new_phase != MirPhase::Analysis(AnalysisPhase::PostCleanup))) + || new_phase == MirPhase::Runtime(RuntimePhase::Optimized); let lint = tcx.sess.opts.unstable_opts.lint_mir & !body.should_skip(); if validate { validate_body(tcx, body, format!("after phase change to {}", new_phase.name())); diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs index 78f97c2eb1448..71d1498b56e50 100644 --- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -12,9 +12,7 @@ pub(super) struct PostAnalysisNormalize; impl<'tcx> crate::MirPass<'tcx> for PostAnalysisNormalize { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // FIXME(#132279): This is used during the phase transition from analysis - // to runtime, so we have to manually specify the correct typing mode. - let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); + let typing_env = body.typing_env(tcx); PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body); } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f1d85166653ff..cffaf90b37d9b 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -395,6 +395,8 @@ fn new_body<'tcx>( ); // Shims do not directly mention any consts. body.set_required_consts(Vec::new()); + // We don't do any analysis on shims. + body.phase = MirPhase::Runtime(RuntimePhase::Initial); body }