From 8834b5ad51263ec70f09d681a10c5ced64f7a782 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 30 Oct 2024 18:22:31 +1100 Subject: coverage: Make `CoverageSuccessors` a struct --- compiler/rustc_mir_transform/src/coverage/graph.rs | 71 ++++++++-------------- 1 file changed, 27 insertions(+), 44 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 168262bf01c..785430b9fb8 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -1,7 +1,7 @@ use std::cmp::Ordering; use std::collections::VecDeque; -use std::iter; use std::ops::{Index, IndexMut}; +use std::{iter, slice}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; @@ -389,34 +389,26 @@ impl BasicCoverageBlockData { /// indicates whether that block can potentially be combined into the same BCB /// as its sole successor. #[derive(Clone, Copy, Debug)] -enum CoverageSuccessors<'a> { - /// The terminator has exactly one straight-line successor, so its block can - /// potentially be combined into the same BCB as that successor. - Chainable(BasicBlock), - /// The block cannot be combined into the same BCB as its successor(s). - NotChainable(&'a [BasicBlock]), - /// Yield terminators are not chainable, and their execution count can also - /// differ from the execution count of their out-edge. - Yield(BasicBlock), +struct CoverageSuccessors<'a> { + /// Coverage-relevant successors of the corresponding terminator. + /// There might be 0, 1, or multiple targets. + targets: &'a [BasicBlock], + /// `Yield` terminators are not chainable, because their sole out-edge is + /// only followed if/when the generator is resumed after the yield. + is_yield: bool, } impl CoverageSuccessors<'_> { fn is_chainable(&self) -> bool { - match self { - Self::Chainable(_) => true, - Self::NotChainable(_) => false, - Self::Yield(_) => false, - } + // If a terminator is out-summable and has exactly one out-edge, then + // it is eligible to be chained into its successor block. + self.is_out_summable() && self.targets.len() == 1 } /// Returns true if the terminator itself is assumed to have the same /// execution count as the sum of its out-edges (assuming no panics). fn is_out_summable(&self) -> bool { - match self { - Self::Chainable(_) => true, - Self::NotChainable(_) => true, - Self::Yield(_) => false, - } + !self.is_yield && !self.targets.is_empty() } } @@ -425,12 +417,7 @@ impl IntoIterator for CoverageSuccessors<'_> { type IntoIter = impl DoubleEndedIterator; fn into_iter(self) -> Self::IntoIter { - match self { - Self::Chainable(bb) | Self::Yield(bb) => { - Some(bb).into_iter().chain((&[]).iter().copied()) - } - Self::NotChainable(bbs) => None.into_iter().chain(bbs.iter().copied()), - } + self.targets.iter().copied() } } @@ -440,14 +427,17 @@ impl IntoIterator for CoverageSuccessors<'_> { // `catch_unwind()` handlers. fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> CoverageSuccessors<'a> { use TerminatorKind::*; - match terminator.kind { + let mut is_yield = false; + let targets = match &terminator.kind { // A switch terminator can have many coverage-relevant successors. - // (If there is exactly one successor, we still treat it as not chainable.) - SwitchInt { ref targets, .. } => CoverageSuccessors::NotChainable(targets.all_targets()), + SwitchInt { targets, .. } => targets.all_targets(), // A yield terminator has exactly 1 successor, but should not be chained, // because its resume edge has a different execution count. - Yield { resume, .. } => CoverageSuccessors::Yield(resume), + Yield { resume, .. } => { + is_yield = true; + slice::from_ref(resume) + } // These terminators have exactly one coverage-relevant successor, // and can be chained into it. @@ -455,24 +445,15 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera | Drop { target, .. } | FalseEdge { real_target: target, .. } | FalseUnwind { real_target: target, .. } - | Goto { target } => CoverageSuccessors::Chainable(target), + | Goto { target } => slice::from_ref(target), // A call terminator can normally be chained, except when it has no // successor because it is known to diverge. - Call { target: maybe_target, .. } => match maybe_target { - Some(target) => CoverageSuccessors::Chainable(target), - None => CoverageSuccessors::NotChainable(&[]), - }, + Call { target: maybe_target, .. } => maybe_target.as_slice(), // An inline asm terminator can normally be chained, except when it // diverges or uses asm goto. - InlineAsm { ref targets, .. } => { - if let [target] = targets[..] { - CoverageSuccessors::Chainable(target) - } else { - CoverageSuccessors::NotChainable(targets) - } - } + InlineAsm { targets, .. } => &targets, // These terminators have no coverage-relevant successors. CoroutineDrop @@ -480,8 +461,10 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera | TailCall { .. } | Unreachable | UnwindResume - | UnwindTerminate(_) => CoverageSuccessors::NotChainable(&[]), - } + | UnwindTerminate(_) => &[], + }; + + CoverageSuccessors { targets, is_yield } } /// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the -- cgit 1.4.1-3-g733a5 From 899d89f64c6cd4ca5fb343a92b1c443d39acfb37 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 31 Oct 2024 13:32:03 +1100 Subject: coverage: Use a standard depth-first search on a custom subgraph --- compiler/rustc_mir_transform/src/coverage/graph.rs | 60 +++++++++++----------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 785430b9fb8..4ec3f0c8b0e 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -145,18 +145,17 @@ impl CoverageGraph { bcbs.push(bcb_data); }; - // Walk the MIR CFG using a Preorder traversal, which starts from `START_BLOCK` and follows - // each block terminator's `successors()`. Coverage spans must map to actual source code, - // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal - // intentionally omits unwind paths. - // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and - // `catch_unwind()` handlers. + // Traverse the MIR control-flow graph, accumulating chains of blocks + // that can be combined into a single node in the coverage graph. + // A depth-first search ensures that if two nodes can be chained + // together, they will be adjacent in the traversal order. // Accumulates a chain of blocks that will be combined into one BCB. let mut basic_blocks = Vec::new(); let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator()); - for bb in short_circuit_preorder(mir_body, filtered_successors) + let subgraph = CoverageRelevantSubgraph::new(&mir_body.basic_blocks); + for bb in graph::depth_first_search(subgraph, mir::START_BLOCK) .filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable) { // If the previous block can't be chained into `bb`, flush the accumulated @@ -599,28 +598,31 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> { } } -fn short_circuit_preorder<'a, 'tcx, F, Iter>( - body: &'a mir::Body<'tcx>, - filtered_successors: F, -) -> impl Iterator + Captures<'a> + Captures<'tcx> -where - F: Fn(BasicBlock) -> Iter, - Iter: IntoIterator, -{ - let mut visited = BitSet::new_empty(body.basic_blocks.len()); - let mut worklist = vec![mir::START_BLOCK]; - - std::iter::from_fn(move || { - while let Some(bb) = worklist.pop() { - if !visited.insert(bb) { - continue; - } - - worklist.extend(filtered_successors(bb)); +/// Wrapper around a [`mir::BasicBlocks`] graph that restricts each node's +/// successors to only the ones considered "relevant" when building a coverage +/// graph. +#[derive(Clone, Copy)] +struct CoverageRelevantSubgraph<'a, 'tcx> { + basic_blocks: &'a mir::BasicBlocks<'tcx>, +} +impl<'a, 'tcx> CoverageRelevantSubgraph<'a, 'tcx> { + fn new(basic_blocks: &'a mir::BasicBlocks<'tcx>) -> Self { + Self { basic_blocks } + } - return Some(bb); - } + fn coverage_successors(&self, bb: BasicBlock) -> CoverageSuccessors<'_> { + bcb_filtered_successors(self.basic_blocks[bb].terminator()) + } +} +impl<'a, 'tcx> graph::DirectedGraph for CoverageRelevantSubgraph<'a, 'tcx> { + type Node = BasicBlock; - None - }) + fn num_nodes(&self) -> usize { + self.basic_blocks.num_nodes() + } +} +impl<'a, 'tcx> graph::Successors for CoverageRelevantSubgraph<'a, 'tcx> { + fn successors(&self, bb: Self::Node) -> impl Iterator { + self.coverage_successors(bb).into_iter() + } } -- cgit 1.4.1-3-g733a5 From 4a70f4bee0baa203636a259fb04929718ee7d0e0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 31 Oct 2024 12:45:41 +1100 Subject: coverage: Simplify logic for chaining multiple blocks into one BCB We only need to take action when the next block cannot be added to the current chain, but the logic is much simpler if we express it in terms of when the block _can_ be added. --- compiler/rustc_mir_transform/src/coverage/graph.rs | 48 ++++++++++------------ 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 4ec3f0c8b0e..092bce1de2c 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -1,7 +1,7 @@ use std::cmp::Ordering; use std::collections::VecDeque; use std::ops::{Index, IndexMut}; -use std::{iter, slice}; +use std::{iter, mem, slice}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; @@ -127,10 +127,10 @@ impl CoverageGraph { let mut bcbs = IndexVec::::with_capacity(num_basic_blocks); let mut bb_to_bcb = IndexVec::from_elem_n(None, num_basic_blocks); - let mut add_basic_coverage_block = |basic_blocks: &mut Vec| { + let mut flush_chain_into_new_bcb = |current_chain: &mut Vec| { // Take the accumulated list of blocks, leaving the vector empty // to be used by subsequent BCBs. - let basic_blocks = std::mem::take(basic_blocks); + let basic_blocks = mem::take(current_chain); let bcb = bcbs.next_index(); for &bb in basic_blocks.iter() { @@ -141,7 +141,7 @@ impl CoverageGraph { bcb_filtered_successors(mir_body[bb].terminator()).is_out_summable() }); let bcb_data = BasicCoverageBlockData { basic_blocks, is_out_summable }; - debug!("adding bcb{}: {:?}", bcb.index(), bcb_data); + debug!("adding {bcb:?}: {bcb_data:?}"); bcbs.push(bcb_data); }; @@ -151,37 +151,31 @@ impl CoverageGraph { // together, they will be adjacent in the traversal order. // Accumulates a chain of blocks that will be combined into one BCB. - let mut basic_blocks = Vec::new(); + let mut current_chain = vec![]; - let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator()); let subgraph = CoverageRelevantSubgraph::new(&mir_body.basic_blocks); for bb in graph::depth_first_search(subgraph, mir::START_BLOCK) .filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable) { - // If the previous block can't be chained into `bb`, flush the accumulated - // blocks into a new BCB, then start building the next chain. - if let Some(&prev) = basic_blocks.last() - && (!filtered_successors(prev).is_chainable() || { - // If `bb` has multiple predecessor blocks, or `prev` isn't - // one of its predecessors, we can't chain and must flush. - let predecessors = &mir_body.basic_blocks.predecessors()[bb]; - predecessors.len() > 1 || !predecessors.contains(&prev) - }) - { - debug!( - terminator_kind = ?mir_body[prev].terminator().kind, - predecessors = ?&mir_body.basic_blocks.predecessors()[bb], - "can't chain from {prev:?} to {bb:?}" - ); - add_basic_coverage_block(&mut basic_blocks); + if let Some(&prev) = current_chain.last() { + // Adding a block to a non-empty chain is allowed if the + // previous block permits chaining, and the current block has + // `prev` as its sole predecessor. + let can_chain = subgraph.coverage_successors(prev).is_out_chainable() + && mir_body.basic_blocks.predecessors()[bb].as_slice() == &[prev]; + if !can_chain { + // The current block can't be added to the existing chain, so + // flush that chain into a new BCB, and start a new chain. + flush_chain_into_new_bcb(&mut current_chain); + } } - basic_blocks.push(bb); + current_chain.push(bb); } - if !basic_blocks.is_empty() { + if !current_chain.is_empty() { debug!("flushing accumulated blocks into one last BCB"); - add_basic_coverage_block(&mut basic_blocks); + flush_chain_into_new_bcb(&mut current_chain); } (bcbs, bb_to_bcb) @@ -398,7 +392,9 @@ struct CoverageSuccessors<'a> { } impl CoverageSuccessors<'_> { - fn is_chainable(&self) -> bool { + /// If `false`, this terminator cannot be chained into another block when + /// building the coverage graph. + fn is_out_chainable(&self) -> bool { // If a terminator is out-summable and has exactly one out-edge, then // it is eligible to be chained into its successor block. self.is_out_summable() && self.targets.len() == 1 -- cgit 1.4.1-3-g733a5 From 843b6e08592affd76a15c6e0e9ceaf73b98d7d5a Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 2 Nov 2024 19:33:00 -0700 Subject: compiler: Directly use rustc_abi in mir_transform --- compiler/rustc_mir_transform/src/abort_unwinding_calls.rs | 12 ++++++------ compiler/rustc_mir_transform/src/coroutine.rs | 2 +- compiler/rustc_mir_transform/src/coroutine/by_move_body.rs | 2 +- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 2 +- compiler/rustc_mir_transform/src/elaborate_box_derefs.rs | 2 +- compiler/rustc_mir_transform/src/elaborate_drops.rs | 2 +- compiler/rustc_mir_transform/src/ffi_unwind_calls.rs | 14 +++++++++----- .../rustc_mir_transform/src/function_item_references.rs | 4 ++-- compiler/rustc_mir_transform/src/inline.rs | 7 +++---- compiler/rustc_mir_transform/src/instsimplify.rs | 6 +++--- compiler/rustc_mir_transform/src/jump_threading.rs | 2 +- compiler/rustc_mir_transform/src/large_enums.rs | 10 +++++----- compiler/rustc_mir_transform/src/match_branches.rs | 2 +- compiler/rustc_mir_transform/src/remove_uninit_drops.rs | 2 +- compiler/rustc_mir_transform/src/shim.rs | 5 ++--- .../rustc_mir_transform/src/shim/async_destructor_ctor.rs | 2 +- compiler/rustc_mir_transform/src/sroa.rs | 2 +- compiler/rustc_mir_transform/src/unreachable_prop.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 9 ++++----- 19 files changed, 45 insertions(+), 44 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 84c8a91b082..03f11885d58 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -1,9 +1,9 @@ +use rustc_abi::ExternAbi; use rustc_ast::InlineAsmOptions; use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::{self, TyCtxt, layout}; use rustc_target::spec::PanicStrategy; -use rustc_target::spec::abi::Abi; /// A pass that runs which is targeted at ensuring that codegen guarantees about /// unwinding are upheld for compilations of panic=abort programs. @@ -38,9 +38,9 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { let body_ty = tcx.type_of(def_id).skip_binder(); let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::CoroutineClosure(..) => Abi::RustCall, - ty::Coroutine(..) => Abi::Rust, + ty::Closure(..) => ExternAbi::RustCall, + ty::CoroutineClosure(..) => ExternAbi::RustCall, + ty::Coroutine(..) => ExternAbi::Rust, ty::Error(_) => return, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; @@ -79,10 +79,10 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { } TerminatorKind::Drop { .. } => { tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Unwind - && layout::fn_can_unwind(tcx, None, Abi::Rust) + && layout::fn_can_unwind(tcx, None, ExternAbi::Rust) } TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => { - layout::fn_can_unwind(tcx, None, Abi::Rust) + layout::fn_can_unwind(tcx, None, ExternAbi::Rust) } TerminatorKind::InlineAsm { options, .. } => { options.contains(InlineAsmOptions::MAY_UNWIND) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 6d5665b4331..063f220501f 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -54,6 +54,7 @@ mod by_move_body; use std::{iter, ops}; pub(super) use by_move_body::coroutine_by_move_body_def_id; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; use rustc_hir as hir; @@ -75,7 +76,6 @@ use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_span::Span; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::sym; -use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::spec::PanicStrategy; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::TyCtxtInferExt as _; diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 2c622b1927e..36eb435c63a 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -69,6 +69,7 @@ //! in case precise captures (edition 2021 closure capture rules) caused the inner coroutine //! to split one field capture into two. +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::steal::Steal; use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; @@ -80,7 +81,6 @@ use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{self, dump_mir}; use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::kw; -use rustc_target::abi::{FieldIdx, VariantIdx}; pub(crate) fn coroutine_by_move_body_def_id<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index dd85d06540d..7d073f1fa57 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -662,7 +662,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { // Exactly one side is known, attempt some algebraic simplifications. (FlatSet::Elem(const_arg), _) | (_, FlatSet::Elem(const_arg)) => { let layout = const_arg.layout; - if !matches!(layout.backend_repr, rustc_target::abi::BackendRepr::Scalar(..)) { + if !matches!(layout.backend_repr, rustc_abi::BackendRepr::Scalar(..)) { return (FlatSet::Top, FlatSet::Top); } diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 57f7a9ef7f5..b909dfa1320 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -2,13 +2,13 @@ //! //! Box is not actually a pointer so it is incorrect to dereference it directly. +use rustc_abi::FieldIdx; use rustc_hir::def_id::DefId; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::{Ty, TyCtxt}; -use rustc_target::abi::FieldIdx; /// Constructs the types used when accessing a Box's pointer fn build_ptr_tys<'tcx>( diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 58e1db19438..74572100db3 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -1,5 +1,6 @@ use std::fmt; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_index::IndexVec; use rustc_index::bit_set::BitSet; use rustc_middle::mir::patch::MirPatch; @@ -14,7 +15,6 @@ use rustc_mir_dataflow::{ Analysis, MoveDataParamEnv, ResultsCursor, on_all_children_bits, on_lookup_result_bits, }; use rustc_span::Span; -use rustc_target::abi::{FieldIdx, VariantIdx}; use tracing::{debug, instrument}; use crate::deref_separator::deref_finder; diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index 99892a1296b..3d560bdf75c 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -1,3 +1,4 @@ +use rustc_abi::ExternAbi; use rustc_hir::def_id::{LOCAL_CRATE, LocalDefId}; use rustc_middle::mir::*; use rustc_middle::query::{LocalCrate, Providers}; @@ -5,7 +6,6 @@ use rustc_middle::ty::{self, TyCtxt, layout}; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::FFI_UNWIND_CALLS; use rustc_target::spec::PanicStrategy; -use rustc_target::spec::abi::Abi; use tracing::debug; use crate::errors; @@ -26,9 +26,9 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { let body_ty = tcx.type_of(def_id).skip_binder(); let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::CoroutineClosure(..) => Abi::RustCall, - ty::Coroutine(..) => Abi::Rust, + ty::Closure(..) => ExternAbi::RustCall, + ty::CoroutineClosure(..) => ExternAbi::RustCall, + ty::Coroutine(..) => ExternAbi::Rust, ty::Error(_) => return false, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; @@ -53,7 +53,11 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { // Rust calls cannot themselves create foreign unwinds. // We assume this is true for intrinsics as well. - if let Abi::RustIntrinsic | Abi::Rust | Abi::RustCall | Abi::RustCold = sig.abi() { + if let ExternAbi::RustIntrinsic + | ExternAbi::Rust + | ExternAbi::RustCall + | ExternAbi::RustCold = sig.abi() + { continue; }; diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index e55aeeac6e0..2945fc6f3d5 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -1,4 +1,5 @@ use itertools::Itertools; +use rustc_abi::ExternAbi; use rustc_hir::def_id::DefId; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -7,7 +8,6 @@ use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES; use rustc_span::Span; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; -use rustc_target::spec::abi::Abi; use crate::errors; @@ -161,7 +161,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { let fn_sig = self.tcx.fn_sig(fn_id).instantiate(self.tcx, fn_args); let unsafety = fn_sig.safety().prefix_str(); let abi = match fn_sig.abi() { - Abi::Rust => String::from(""), + ExternAbi::Rust => String::from(""), other_abi => { let mut s = String::from("extern \""); s.push_str(other_abi.name()); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 404470db5c5..e95ab4ffe16 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -3,6 +3,7 @@ use std::iter; use std::ops::{Range, RangeFrom}; +use rustc_abi::{ExternAbi, FieldIdx}; use rustc_attr::InlineAttr; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -18,8 +19,6 @@ use rustc_middle::ty::{ use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::source_map::Spanned; use rustc_span::sym; -use rustc_target::abi::FieldIdx; -use rustc_target::spec::abi::Abi; use tracing::{debug, instrument, trace, trace_span}; use crate::cost_checker::CostChecker; @@ -254,7 +253,7 @@ impl<'tcx> Inliner<'tcx> { trace!(?output_type, ?destination_ty); return Err("failed to normalize return type"); } - if callsite.fn_sig.abi() == Abi::RustCall { + if callsite.fn_sig.abi() == ExternAbi::RustCall { // FIXME: Don't inline user-written `extern "rust-call"` functions, // since this is generally perf-negative on rustc, and we hope that // LLVM will inline these functions instead. @@ -808,7 +807,7 @@ impl<'tcx> Inliner<'tcx> { // tmp2 = tuple_tmp.2 // // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`. - if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() { + if callsite.fn_sig.abi() == ExternAbi::RustCall && callee_body.spread_arg.is_none() { // FIXME(edition_2024): switch back to a normal method call. let mut args = <_>::into_iter(args); let self_ = self.create_temp_if_necessary( diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 8bcc91b4488..9471c1b2a9a 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -1,5 +1,6 @@ //! Performs various peephole optimizations. +use rustc_abi::ExternAbi; use rustc_ast::attr; use rustc_hir::LangItem; use rustc_middle::bug; @@ -8,7 +9,6 @@ use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, layout}; use rustc_span::sym; use rustc_span::symbol::Symbol; -use rustc_target::spec::abi::Abi; use crate::simplify::simplify_duplicate_switch_targets; use crate::take_array; @@ -321,8 +321,8 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { let body_ty = self.tcx.type_of(def_id).skip_binder(); let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::Coroutine(..) => Abi::Rust, + ty::Closure(..) => ExternAbi::RustCall, + ty::Coroutine(..) => ExternAbi::Rust, _ => bug!("unexpected body ty: {:?}", body_ty), }; diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 9b9b0b705bf..3772589ac4e 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -35,6 +35,7 @@ //! Likewise, applying the optimisation can create a lot of new MIR, so we bound the instruction //! cost by `MAX_COST`. +use rustc_abi::{TagEncoding, Variants}; use rustc_arena::DroplessArena; use rustc_const_eval::const_eval::DummyMachine; use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}; @@ -50,7 +51,6 @@ use rustc_middle::ty::{self, ScalarInt, TyCtxt}; use rustc_mir_dataflow::lattice::HasBottom; use rustc_mir_dataflow::value_analysis::{Map, PlaceIndex, State, TrackElem}; use rustc_span::DUMMY_SP; -use rustc_target::abi::{TagEncoding, Variants}; use tracing::{debug, instrument, trace}; use crate::cost_checker::CostChecker; diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 3e263aa4067..fa659a56a27 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -1,10 +1,10 @@ +use rustc_abi::{HasDataLayout, Size, TagEncoding, Variants}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::*; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt}; use rustc_session::Session; -use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants}; /// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large /// enough discrepancy between them. @@ -249,8 +249,8 @@ impl EnumSizeOpt { macro_rules! encode_store { ($curr_idx: expr, $endian: expr, $bytes: expr) => { let bytes = match $endian { - rustc_target::abi::Endian::Little => $bytes.to_le_bytes(), - rustc_target::abi::Endian::Big => $bytes.to_be_bytes(), + rustc_abi::Endian::Little => $bytes.to_le_bytes(), + rustc_abi::Endian::Big => $bytes.to_be_bytes(), }; for (i, b) in bytes.into_iter().enumerate() { data[$curr_idx + i] = b; @@ -263,10 +263,10 @@ impl EnumSizeOpt { target_bytes * adt_def.discriminant_for_variant(tcx, var_idx).val as usize; let sz = layout.size; match ptr_sized_int { - rustc_target::abi::Integer::I32 => { + rustc_abi::Integer::I32 => { encode_store!(curr_idx, data_layout.endian, sz.bytes() as u32); } - rustc_target::abi::Integer::I64 => { + rustc_abi::Integer::I64 => { encode_store!(curr_idx, data_layout.endian, sz.bytes()); } _ => unreachable!(), diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index ad3126f66a6..237227f5294 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -1,11 +1,11 @@ use std::iter; +use rustc_abi::Integer; use rustc_index::IndexSlice; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt}; -use rustc_target::abi::Integer; use rustc_type_ir::TyKind::*; use super::simplify::simplify_cfg; diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 55dd96100b0..20c34a7469e 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -1,10 +1,10 @@ +use rustc_abi::FieldIdx; use rustc_index::bit_set::ChunkedBitSet; use rustc_middle::mir::{Body, TerminatorKind}; use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{Analysis, MaybeReachable, move_path_children_matching}; -use rustc_target::abi::FieldIdx; /// Removes `Drop` terminators whose target is known to be uninitialized at /// that point. diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index e872878a751..ffa11f5b213 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1,6 +1,7 @@ use std::assert_matches::assert_matches; use std::{fmt, iter}; +use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -15,8 +16,6 @@ use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; -use rustc_target::spec::abi::Abi; use tracing::{debug, instrument}; use crate::{ @@ -905,7 +904,7 @@ fn build_call_shim<'tcx>( let mut body = new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span); - if let Abi::RustCall = sig.abi { + if let ExternAbi::RustCall = sig.abi { body.spread_arg = Some(Local::new(sig.inputs().len())); } diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 71723f040b3..f1672272862 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -1,6 +1,7 @@ use std::iter; use itertools::Itertools; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_ast::Mutability; use rustc_const_eval::interpret; use rustc_hir::def_id::DefId; @@ -18,7 +19,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::source_map::respan; use rustc_span::{Span, Symbol}; -use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::spec::PanicStrategy; use tracing::debug; diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 2de0059bc7f..53bbb122096 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -1,3 +1,4 @@ +use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_hir::LangItem; use rustc_index::IndexVec; @@ -8,7 +9,6 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; use tracing::{debug, instrument}; pub(super) struct ScalarReplacementOfAggregates; diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index f3dafd13824..9cd32459c7b 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -2,13 +2,13 @@ //! when all of their successors are unreachable. This is achieved through a //! post-order traversal of the blocks. +use rustc_abi::Size; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; -use rustc_target::abi::Size; pub(super) struct UnreachablePropagation; diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 8109a9b8ba0..ae4e6ea6a74 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1,5 +1,6 @@ //! Validates the MIR to ensure that invariants are upheld. +use rustc_abi::{ExternAbi, FIRST_VARIANT, Size}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::LangItem; use rustc_index::IndexVec; @@ -15,8 +16,6 @@ use rustc_middle::ty::{ Variance, }; use rustc_middle::{bug, span_bug}; -use rustc_target::abi::{FIRST_VARIANT, Size}; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::ObligationCtxt; use rustc_type_ir::Upcast; @@ -60,9 +59,9 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { let body_ty = tcx.type_of(def_id).skip_binder(); let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::CoroutineClosure(..) => Abi::RustCall, - ty::Coroutine(..) => Abi::Rust, + ty::Closure(..) => ExternAbi::RustCall, + ty::CoroutineClosure(..) => ExternAbi::RustCall, + ty::Coroutine(..) => ExternAbi::Rust, // No need to do MIR validation on error bodies ty::Error(_) => return, _ => { -- cgit 1.4.1-3-g733a5 From c904c6aaffa10f92e8f203f69bd8b87b0b0f4353 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 31 Oct 2024 12:33:12 +1100 Subject: Remove `ResultsVisitable`. Now that `Results` is the only impl of `ResultsVisitable`, the trait can be removed. This simplifies things by removining unnecessary layers of indirection and abstraction. - `ResultsVisitor` is simpler. - Its type parameter changes from `R` (an analysis result) to the simpler `A` (an analysis). - It no longer needs the `Domain` associated type, because it can use `A::Domain`. - Occurrences of `R` become `Results<'tcx, A>`, because there is now only one kind of analysis results. - `save_as_intervals` also changes type parameter from `R` to `A`. - The `results.reconstruct_*` method calls are replaced with `results.analysis.apply_*` method calls, which are equivalent. - `Direction::visit_results_in_block` is simpler, with a single generic param (`A`) instead of two (`D` and `R`/`F`, with a bound connecting them). Likewise for `visit_results`. - The `ResultsVisitor` impls for `MirBorrowCtxt` and `StorageConflictVisitor` are now specific about the type of the analysis results they work with. They both used to have a type param `R` but they weren't genuinely generic. In both cases there was only a single results type that made sense to instantiate them with. --- compiler/rustc_borrowck/src/lib.rs | 16 +-- .../rustc_mir_dataflow/src/framework/direction.rs | 56 ++++---- .../rustc_mir_dataflow/src/framework/graphviz.rs | 16 +-- compiler/rustc_mir_dataflow/src/framework/mod.rs | 2 +- .../rustc_mir_dataflow/src/framework/results.rs | 4 +- .../rustc_mir_dataflow/src/framework/visitor.rs | 143 ++++----------------- compiler/rustc_mir_dataflow/src/lib.rs | 4 +- compiler/rustc_mir_dataflow/src/points.rs | 21 ++- compiler/rustc_mir_transform/src/coroutine.rs | 18 ++- .../rustc_mir_transform/src/dataflow_const_prop.rs | 12 +- 10 files changed, 91 insertions(+), 201 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 817d407c38c..7eaf265d410 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -42,7 +42,7 @@ use rustc_mir_dataflow::impls::{ use rustc_mir_dataflow::move_paths::{ InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex, }; -use rustc_mir_dataflow::{Analysis, EntrySets, Results}; +use rustc_mir_dataflow::{Analysis, EntrySets, Results, ResultsVisitor, visit_results}; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; use smallvec::SmallVec; @@ -318,7 +318,7 @@ fn do_mir_borrowck<'tcx>( mbcx.report_region_errors(nll_errors); let mut flow_results = get_flow_results(tcx, body, &move_data, &borrow_set, ®ioncx); - rustc_mir_dataflow::visit_results( + visit_results( body, traversal::reverse_postorder(body).map(|(bb, _)| bb), &mut flow_results, @@ -607,14 +607,10 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { // 2. loans made in overlapping scopes do not conflict // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way -impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> - for MirBorrowckCtxt<'a, '_, 'tcx> -{ - type Domain = BorrowckDomain<'a, 'tcx>; - +impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> { fn visit_statement_before_primary_effect( &mut self, - _results: &mut R, + _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, state: &BorrowckDomain<'a, 'tcx>, stmt: &'a Statement<'tcx>, location: Location, @@ -686,7 +682,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> fn visit_terminator_before_primary_effect( &mut self, - _results: &mut R, + _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, state: &BorrowckDomain<'a, 'tcx>, term: &'a Terminator<'tcx>, loc: Location, @@ -799,7 +795,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> fn visit_terminator_after_primary_effect( &mut self, - _results: &mut R, + _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, state: &BorrowckDomain<'a, 'tcx>, term: &'a Terminator<'tcx>, loc: Location, diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 3e01f0512c4..9a5cf9d4e84 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -4,8 +4,8 @@ use rustc_middle::mir::{ self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, }; -use super::visitor::{ResultsVisitable, ResultsVisitor}; -use super::{Analysis, Effect, EffectIndex, SwitchIntTarget}; +use super::visitor::ResultsVisitor; +use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget}; pub trait Direction { const IS_FORWARD: bool; @@ -33,14 +33,14 @@ pub trait Direction { where A: Analysis<'tcx>; - fn visit_results_in_block<'mir, 'tcx, D, R>( - state: &mut D, + fn visit_results_in_block<'mir, 'tcx, A>( + state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = D>; + A: Analysis<'tcx>; fn join_state_into_successors_of<'tcx, A>( analysis: &mut A, @@ -53,7 +53,7 @@ pub trait Direction { A: Analysis<'tcx>; } -/// Dataflow that runs from the exit of a block (the terminator), to its entry (the first statement). +/// Dataflow that runs from the exit of a block (terminator), to its entry (the first statement). pub struct Backward; impl Direction for Backward { @@ -157,32 +157,32 @@ impl Direction for Backward { analysis.apply_statement_effect(state, statement, location); } - fn visit_results_in_block<'mir, 'tcx, D, R>( - state: &mut D, + fn visit_results_in_block<'mir, 'tcx, A>( + state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = D>, + A: Analysis<'tcx>, { - results.reset_to_block_entry(state, block); + state.clone_from(results.entry_set_for_block(block)); vis.visit_block_end(state); // Terminator let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.reconstruct_before_terminator_effect(state, term, loc); + results.analysis.apply_before_terminator_effect(state, term, loc); vis.visit_terminator_before_primary_effect(results, state, term, loc); - results.reconstruct_terminator_effect(state, term, loc); + results.analysis.apply_terminator_effect(state, term, loc); vis.visit_terminator_after_primary_effect(results, state, term, loc); for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() { let loc = Location { block, statement_index }; - results.reconstruct_before_statement_effect(state, stmt, loc); + results.analysis.apply_before_statement_effect(state, stmt, loc); vis.visit_statement_before_primary_effect(results, state, stmt, loc); - results.reconstruct_statement_effect(state, stmt, loc); + results.analysis.apply_statement_effect(state, stmt, loc); vis.visit_statement_after_primary_effect(results, state, stmt, loc); } @@ -389,32 +389,32 @@ impl Direction for Forward { } } - fn visit_results_in_block<'mir, 'tcx, F, R>( - state: &mut F, + fn visit_results_in_block<'mir, 'tcx, A>( + state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = F>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = F>, + A: Analysis<'tcx>, { - results.reset_to_block_entry(state, block); + state.clone_from(results.entry_set_for_block(block)); vis.visit_block_start(state); for (statement_index, stmt) in block_data.statements.iter().enumerate() { let loc = Location { block, statement_index }; - results.reconstruct_before_statement_effect(state, stmt, loc); + results.analysis.apply_before_statement_effect(state, stmt, loc); vis.visit_statement_before_primary_effect(results, state, stmt, loc); - results.reconstruct_statement_effect(state, stmt, loc); + results.analysis.apply_statement_effect(state, stmt, loc); vis.visit_statement_after_primary_effect(results, state, stmt, loc); } let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.reconstruct_before_terminator_effect(state, term, loc); + results.analysis.apply_before_terminator_effect(state, term, loc); vis.visit_terminator_before_primary_effect(results, state, term, loc); - results.reconstruct_terminator_effect(state, term, loc); + results.analysis.apply_terminator_effect(state, term, loc); vis.visit_terminator_after_primary_effect(results, state, term, loc); vis.visit_block_end(state); diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index bac75b972f9..98a4f58cb5d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -544,20 +544,18 @@ impl StateDiffCollector { } } -impl<'tcx, A> ResultsVisitor<'_, 'tcx, Results<'tcx, A>> for StateDiffCollector +impl<'tcx, A> ResultsVisitor<'_, 'tcx, A> for StateDiffCollector where A: Analysis<'tcx>, A::Domain: DebugWithContext, { - type Domain = A::Domain; - - fn visit_block_start(&mut self, state: &Self::Domain) { + fn visit_block_start(&mut self, state: &A::Domain) { if A::Direction::IS_FORWARD { self.prev_state.clone_from(state); } } - fn visit_block_end(&mut self, state: &Self::Domain) { + fn visit_block_end(&mut self, state: &A::Domain) { if A::Direction::IS_BACKWARD { self.prev_state.clone_from(state); } @@ -566,7 +564,7 @@ where fn visit_statement_before_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, ) { @@ -579,7 +577,7 @@ where fn visit_statement_after_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, ) { @@ -590,7 +588,7 @@ where fn visit_terminator_before_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, ) { @@ -603,7 +601,7 @@ where fn visit_terminator_after_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, ) { diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 4ad68193528..244dfe26ad3 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -56,7 +56,7 @@ pub use self::cursor::ResultsCursor; pub use self::direction::{Backward, Direction, Forward}; pub use self::lattice::{JoinSemiLattice, MaybeReachable}; pub use self::results::{EntrySets, Results}; -pub use self::visitor::{ResultsVisitable, ResultsVisitor, visit_results}; +pub use self::visitor::{ResultsVisitor, visit_results}; /// Analysis domains are all bitsets of various kinds. This trait holds /// operations needed by all of them. diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index 2269c4ec226..ff6cafbfbae 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -51,7 +51,7 @@ where &mut self, body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, - vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { visit_results(body, blocks, self, vis) } @@ -59,7 +59,7 @@ where pub fn visit_reachable_with<'mir>( &mut self, body: &'mir mir::Body<'tcx>, - vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { let blocks = traversal::reachable(body); visit_results(body, blocks.map(|(bb, _)| bb), self, vis) diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs index 3d6b008a684..5c7539eed4d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -4,15 +4,15 @@ use super::{Analysis, Direction, Results}; /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the /// dataflow state at that location. -pub fn visit_results<'mir, 'tcx, D, R>( +pub fn visit_results<'mir, 'tcx, A>( body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = D>, + A: Analysis<'tcx>, { - let mut state = results.bottom_value(body); + let mut state = results.analysis.bottom_value(body); #[cfg(debug_assertions)] let reachable_blocks = mir::traversal::reachable_as_bitset(body); @@ -22,23 +22,23 @@ pub fn visit_results<'mir, 'tcx, D, R>( assert!(reachable_blocks.contains(block)); let block_data = &body[block]; - R::Direction::visit_results_in_block(&mut state, block, block_data, results, vis); + A::Direction::visit_results_in_block(&mut state, block, block_data, results, vis); } } -/// A visitor over the results of an `Analysis`. The type parameter `R` is the results type being -/// visited. -pub trait ResultsVisitor<'mir, 'tcx, R> { - type Domain; - - fn visit_block_start(&mut self, _state: &Self::Domain) {} +/// A visitor over the results of an `Analysis`. +pub trait ResultsVisitor<'mir, 'tcx, A> +where + A: Analysis<'tcx>, +{ + fn visit_block_start(&mut self, _state: &A::Domain) {} /// Called with the `before_statement_effect` of the given statement applied to `state` but not /// its `statement_effect`. fn visit_statement_before_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, _location: Location, ) { @@ -48,19 +48,19 @@ pub trait ResultsVisitor<'mir, 'tcx, R> { /// statement applied to `state`. fn visit_statement_after_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, _location: Location, ) { } - /// Called with the `before_terminator_effect` of the given terminator applied to `state` but not - /// its `terminator_effect`. + /// Called with the `before_terminator_effect` of the given terminator applied to `state` but + /// not its `terminator_effect`. fn visit_terminator_before_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, _location: Location, ) { @@ -72,109 +72,12 @@ pub trait ResultsVisitor<'mir, 'tcx, R> { /// The `call_return_effect` (if one exists) will *not* be applied to `state`. fn visit_terminator_after_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, _location: Location, ) { } - fn visit_block_end(&mut self, _state: &Self::Domain) {} -} - -/// Things that can be visited by a `ResultsVisitor`. -/// -/// This trait exists so that we can visit the results of one or more dataflow analyses -/// simultaneously. -pub trait ResultsVisitable<'tcx> { - type Direction: Direction; - type Domain; - - /// Creates an empty `Domain` to hold the transient state for these dataflow results. - /// - /// The value of the newly created `Domain` will be overwritten by `reset_to_block_entry` - /// before it can be observed by a `ResultsVisitor`. - fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain; - - fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock); - - fn reconstruct_before_statement_effect( - &mut self, - state: &mut Self::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ); - - fn reconstruct_statement_effect( - &mut self, - state: &mut Self::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ); - - fn reconstruct_before_terminator_effect( - &mut self, - state: &mut Self::Domain, - terminator: &mir::Terminator<'tcx>, - location: Location, - ); - - fn reconstruct_terminator_effect( - &mut self, - state: &mut Self::Domain, - terminator: &mir::Terminator<'tcx>, - location: Location, - ); -} - -impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A> -where - A: Analysis<'tcx>, -{ - type Domain = A::Domain; - type Direction = A::Direction; - - fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { - self.analysis.bottom_value(body) - } - - fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock) { - state.clone_from(self.entry_set_for_block(block)); - } - - fn reconstruct_before_statement_effect( - &mut self, - state: &mut Self::Domain, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - self.analysis.apply_before_statement_effect(state, stmt, loc); - } - - fn reconstruct_statement_effect( - &mut self, - state: &mut Self::Domain, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - self.analysis.apply_statement_effect(state, stmt, loc); - } - - fn reconstruct_before_terminator_effect( - &mut self, - state: &mut Self::Domain, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - self.analysis.apply_before_terminator_effect(state, term, loc); - } - - fn reconstruct_terminator_effect( - &mut self, - state: &mut Self::Domain, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - self.analysis.apply_terminator_effect(state, term, loc); - } + fn visit_block_end(&mut self, _state: &A::Domain) {} } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 8ebe7d59309..ab1453f1ed0 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -19,8 +19,8 @@ pub use self::drop_flag_effects::{ }; pub use self::framework::{ Analysis, Backward, Direction, EntrySets, Forward, GenKill, JoinSemiLattice, MaybeReachable, - Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, - lattice, visit_results, + Results, ResultsCursor, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice, + visit_results, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs index 73abb669a11..10f1e009855 100644 --- a/compiler/rustc_mir_dataflow/src/points.rs +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -3,7 +3,7 @@ use rustc_index::interval::SparseIntervalMatrix; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{self, BasicBlock, Body, Location}; -use crate::framework::{ResultsVisitable, ResultsVisitor, visit_results}; +use crate::framework::{Analysis, Results, ResultsVisitor, visit_results}; /// Maps between a `Location` and a `PointIndex` (and vice versa). pub struct DenseLocationMap { @@ -95,14 +95,14 @@ rustc_index::newtype_index! { } /// Add points depending on the result of the given dataflow analysis. -pub fn save_as_intervals<'tcx, N, R>( +pub fn save_as_intervals<'tcx, N, A>( elements: &DenseLocationMap, body: &mir::Body<'tcx>, - mut results: R, + mut results: Results<'tcx, A>, ) -> SparseIntervalMatrix where N: Idx, - R: ResultsVisitable<'tcx, Domain = BitSet>, + A: Analysis<'tcx, Domain = BitSet>, { let values = SparseIntervalMatrix::new(elements.num_points()); let mut visitor = Visitor { elements, values }; @@ -120,16 +120,15 @@ struct Visitor<'a, N: Idx> { values: SparseIntervalMatrix, } -impl<'mir, 'tcx, R, N> ResultsVisitor<'mir, 'tcx, R> for Visitor<'_, N> +impl<'mir, 'tcx, A, N> ResultsVisitor<'mir, 'tcx, A> for Visitor<'_, N> where + A: Analysis<'tcx, Domain = BitSet>, N: Idx, { - type Domain = BitSet; - fn visit_statement_after_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, A>, + state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, location: Location, ) { @@ -142,8 +141,8 @@ where fn visit_terminator_after_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, A>, + state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, location: Location, ) { diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 063f220501f..c2666caa1e8 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -68,11 +68,11 @@ use rustc_middle::ty::{ self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode, }; use rustc_middle::{bug, span_bug}; -use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, }; use rustc_mir_dataflow::storage::always_storage_live_locals; +use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor}; use rustc_span::Span; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::sym; @@ -817,9 +817,9 @@ impl ops::Deref for CoroutineSavedLocals { /// computation; see `CoroutineLayout` for more. fn compute_storage_conflicts<'mir, 'tcx>( body: &'mir Body<'tcx>, - saved_locals: &CoroutineSavedLocals, + saved_locals: &'mir CoroutineSavedLocals, always_live_locals: BitSet, - mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, + mut requires_storage: Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, ) -> BitMatrix { assert_eq!(body.local_decls.len(), saved_locals.domain_size()); @@ -877,15 +877,13 @@ struct StorageConflictVisitor<'a, 'tcx> { eligible_storage_live: BitSet, } -impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> +impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>> for StorageConflictVisitor<'a, 'tcx> { - type Domain = BitSet; - fn visit_statement_before_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, + state: &BitSet, _statement: &'a Statement<'tcx>, loc: Location, ) { @@ -894,8 +892,8 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> fn visit_terminator_before_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, + state: &BitSet, _terminator: &'a Terminator<'tcx>, loc: Location, ) { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 7d073f1fa57..ab6460c490b 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -941,16 +941,12 @@ fn try_write_constant<'tcx>( interp_ok(()) } -impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx>>> - for Collector<'_, 'tcx> -{ - type Domain = State>; - +impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> { #[instrument(level = "trace", skip(self, results, statement))] fn visit_statement_before_primary_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, - state: &Self::Domain, + state: &State>, statement: &'mir Statement<'tcx>, location: Location, ) { @@ -972,7 +968,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx fn visit_statement_after_primary_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, - state: &Self::Domain, + state: &State>, statement: &'mir Statement<'tcx>, location: Location, ) { @@ -997,7 +993,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx fn visit_terminator_before_primary_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, - state: &Self::Domain, + state: &State>, terminator: &'mir Terminator<'tcx>, location: Location, ) { -- cgit 1.4.1-3-g733a5 From 7c769959505efaf8d6717e67e8def06b5f1a515d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 6 Nov 2024 13:05:21 +1100 Subject: coverage: Pass `ExtractedHirInfo` to `make_source_region` This isn't strictly necessary, but makes it easier to distinguish `body_span` from the specific `span` being processed. --- compiler/rustc_mir_transform/src/coverage/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 2e4c503f3ce..bc698e9ebf6 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -23,7 +23,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, Pos, RelativeBytePos, Span, Symbol}; -use tracing::{debug, debug_span, instrument, trace}; +use tracing::{debug, debug_span, trace}; use crate::coverage::counters::{CounterIncrementSite, CoverageCounters}; use crate::coverage::graph::CoverageGraph; @@ -154,7 +154,7 @@ fn create_mappings<'tcx>( let term_for_bcb = |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); - let region_for_span = |span: Span| make_source_region(source_map, file_name, span, body_span); + let region_for_span = |span: Span| make_source_region(source_map, hir_info, file_name, span); // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { @@ -408,12 +408,11 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb /// but it's hard to rule out entirely (especially in the presence of complex macros /// or other expansions), and if it does happen then skipping a span or function is /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. -#[instrument(level = "debug", skip(source_map))] fn make_source_region( source_map: &SourceMap, + hir_info: &ExtractedHirInfo, file_name: Symbol, span: Span, - body_span: Span, ) -> Option { let lo = span.lo(); let hi = span.hi(); @@ -441,6 +440,7 @@ fn make_source_region( // worth of bytes, so that it is more visible in `llvm-cov` reports. // We do this after resolving line/column numbers, so that empty spans at the // end of a line get an extra column instead of wrapping to the next line. + let body_span = hir_info.body_span; if span.is_empty() && body_span.contains(span) && let Some(src) = &file.src -- cgit 1.4.1-3-g733a5 From 996bdabc2a31cd86086b6f9beba3a8c58c8ceb8a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 4 Nov 2024 14:53:52 +1100 Subject: coverage: Remove unhelpful code for handling multiple files per function Functions currently can't have mappings in multiple files, and if that ever changes (e.g. to properly support expansion regions), this code will need to be completely overhauled anyway. --- .../rustc_codegen_llvm/src/coverageinfo/ffi.rs | 2 +- .../src/coverageinfo/map_data.rs | 8 +- .../rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 106 +++++++++++---------- compiler/rustc_middle/src/mir/coverage.rs | 11 +-- compiler/rustc_middle/src/mir/pretty.rs | 4 +- compiler/rustc_mir_transform/src/coverage/mod.rs | 28 ++---- .../branch_match_arms.main.InstrumentCoverage.diff | 13 +-- ...instrument_coverage.bar.InstrumentCoverage.diff | 3 +- ...nstrument_coverage.main.InstrumentCoverage.diff | 11 ++- ..._coverage_cleanup.main.CleanupPostBorrowck.diff | 11 ++- ...t_coverage_cleanup.main.InstrumentCoverage.diff | 11 ++- 11 files changed, 98 insertions(+), 110 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index feac97f3e2b..a73ee0a3e07 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -138,7 +138,7 @@ pub(crate) struct CoverageSpan { impl CoverageSpan { pub(crate) fn from_source_region(file_id: u32, code_region: &SourceRegion) -> Self { - let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; + let &SourceRegion { start_line, start_col, end_line, end_col } = code_region; // Internally, LLVM uses the high bit of `end_col` to distinguish between // code regions and gap regions, so it can't be used by the column number. assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}"); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 5ed640b840e..e3c0df27883 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -6,7 +6,6 @@ use rustc_middle::mir::coverage::{ SourceRegion, }; use rustc_middle::ty::Instance; -use rustc_span::Symbol; use tracing::{debug, instrument}; use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; @@ -180,7 +179,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { } pub(crate) struct FunctionCoverage<'tcx> { - function_coverage_info: &'tcx FunctionCoverageInfo, + pub(crate) function_coverage_info: &'tcx FunctionCoverageInfo, is_used: bool, counters_seen: BitSet, @@ -199,11 +198,6 @@ impl<'tcx> FunctionCoverage<'tcx> { if self.is_used { self.function_coverage_info.function_source_hash } else { 0 } } - /// Returns an iterator over all filenames used by this function's mappings. - pub(crate) fn all_file_names(&self) -> impl Iterator + Captures<'_> { - self.function_coverage_info.mappings.iter().map(|mapping| mapping.source_region.file_name) - } - /// Convert this function's coverage expression data into a form that can be /// passed through FFI to LLVM. pub(crate) fn counter_expressions( diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 9effcaede1c..488ce620746 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -11,8 +11,10 @@ use rustc_index::IndexVec; use rustc_middle::mir::coverage::MappingKind; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, mir}; -use rustc_span::Symbol; +use rustc_session::RemapFileNameExt; +use rustc_session::config::RemapPathScopeComponents; use rustc_span::def_id::DefIdSet; +use rustc_span::{Span, Symbol}; use rustc_target::spec::HasTargetSpec; use tracing::debug; @@ -69,8 +71,10 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { .map(|(instance, function_coverage)| (instance, function_coverage.into_finished())) .collect::>(); - let all_file_names = - function_coverage_entries.iter().flat_map(|(_, fn_cov)| fn_cov.all_file_names()); + let all_file_names = function_coverage_entries + .iter() + .map(|(_, fn_cov)| fn_cov.function_coverage_info.body_span) + .map(|span| span_file_name(tcx, span)); let global_file_table = GlobalFileTable::new(all_file_names); // Encode all filenames referenced by coverage mappings in this CGU. @@ -95,7 +99,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { let is_used = function_coverage.is_used(); let coverage_mapping_buffer = - encode_mappings_for_function(&global_file_table, &function_coverage); + encode_mappings_for_function(tcx, &global_file_table, &function_coverage); if coverage_mapping_buffer.is_empty() { if function_coverage.is_used() { @@ -232,12 +236,20 @@ impl VirtualFileMapping { } } +fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol { + let source_file = tcx.sess.source_map().lookup_source_file(span.lo()); + let name = + source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(); + Symbol::intern(&name) +} + /// Using the expressions and counter regions collected for a single function, /// generate the variable-sized payload of its corresponding `__llvm_covfun` /// entry. The payload is returned as a vector of bytes. /// /// Newly-encountered filenames will be added to the global file table. fn encode_mappings_for_function( + tcx: TyCtxt<'_>, global_file_table: &GlobalFileTable, function_coverage: &FunctionCoverage<'_>, ) -> Vec { @@ -254,53 +266,45 @@ fn encode_mappings_for_function( let mut mcdc_branch_regions = vec![]; let mut mcdc_decision_regions = vec![]; - // Group mappings into runs with the same filename, preserving the order - // yielded by `FunctionCoverage`. - // Prepare file IDs for each filename, and prepare the mapping data so that - // we can pass it through FFI to LLVM. - for (file_name, counter_regions_for_file) in - &counter_regions.group_by(|(_, region)| region.file_name) - { - // Look up the global file ID for this filename. - let global_file_id = global_file_table.global_file_id_for_file_name(file_name); - - // Associate that global file ID with a local file ID for this function. - let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id); - debug!(" file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'"); - - // For each counter/region pair in this function+file, convert it to a - // form suitable for FFI. - for (mapping_kind, region) in counter_regions_for_file { - debug!("Adding counter {mapping_kind:?} to map for {region:?}"); - let span = ffi::CoverageSpan::from_source_region(local_file_id.as_u32(), region); - match mapping_kind { - MappingKind::Code(term) => { - code_regions - .push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) }); - } - MappingKind::Branch { true_term, false_term } => { - branch_regions.push(ffi::BranchRegion { - span, - true_counter: ffi::Counter::from_term(true_term), - false_counter: ffi::Counter::from_term(false_term), - }); - } - MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => { - mcdc_branch_regions.push(ffi::MCDCBranchRegion { - span, - true_counter: ffi::Counter::from_term(true_term), - false_counter: ffi::Counter::from_term(false_term), - mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params), - }); - } - MappingKind::MCDCDecision(mcdc_decision_params) => { - mcdc_decision_regions.push(ffi::MCDCDecisionRegion { - span, - mcdc_decision_params: ffi::mcdc::DecisionParameters::from( - mcdc_decision_params, - ), - }); - } + // Currently a function's mappings must all be in the same file as its body span. + let file_name = span_file_name(tcx, function_coverage.function_coverage_info.body_span); + + // Look up the global file ID for that filename. + let global_file_id = global_file_table.global_file_id_for_file_name(file_name); + + // Associate that global file ID with a local file ID for this function. + let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id); + debug!(" file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'"); + + // For each counter/region pair in this function+file, convert it to a + // form suitable for FFI. + for (mapping_kind, region) in counter_regions { + debug!("Adding counter {mapping_kind:?} to map for {region:?}"); + let span = ffi::CoverageSpan::from_source_region(local_file_id.as_u32(), region); + match mapping_kind { + MappingKind::Code(term) => { + code_regions.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) }); + } + MappingKind::Branch { true_term, false_term } => { + branch_regions.push(ffi::BranchRegion { + span, + true_counter: ffi::Counter::from_term(true_term), + false_counter: ffi::Counter::from_term(false_term), + }); + } + MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => { + mcdc_branch_regions.push(ffi::MCDCBranchRegion { + span, + true_counter: ffi::Counter::from_term(true_term), + false_counter: ffi::Counter::from_term(false_term), + mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params), + }); + } + MappingKind::MCDCDecision(mcdc_decision_params) => { + mcdc_decision_regions.push(ffi::MCDCDecisionRegion { + span, + mcdc_decision_params: ffi::mcdc::DecisionParameters::from(mcdc_decision_params), + }); } } } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 4a876dc1228..11a4e7f89a7 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -4,7 +4,7 @@ use std::fmt::{self, Debug, Formatter}; use rustc_index::IndexVec; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; rustc_index::newtype_index! { /// Used by [`CoverageKind::BlockMarker`] to mark blocks during THIR-to-MIR @@ -158,7 +158,6 @@ impl Debug for CoverageKind { #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] #[derive(TypeFoldable, TypeVisitable)] pub struct SourceRegion { - pub file_name: Symbol, pub start_line: u32, pub start_col: u32, pub end_line: u32, @@ -167,11 +166,8 @@ pub struct SourceRegion { impl Debug for SourceRegion { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - write!( - fmt, - "{}:{}:{} - {}:{}", - self.file_name, self.start_line, self.start_col, self.end_line, self.end_col - ) + let &Self { start_line, start_col, end_line, end_col } = self; + write!(fmt, "{start_line}:{start_col} - {end_line}:{end_col}") } } @@ -246,6 +242,7 @@ pub struct Mapping { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct FunctionCoverageInfo { pub function_source_hash: u64, + pub body_span: Span, pub num_counters: usize, pub mcdc_bitmap_bits: usize, pub expressions: IndexVec, diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index d0f93c19e44..f0e2b7a376c 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -596,8 +596,10 @@ fn write_function_coverage_info( function_coverage_info: &coverage::FunctionCoverageInfo, w: &mut dyn io::Write, ) -> io::Result<()> { - let coverage::FunctionCoverageInfo { expressions, mappings, .. } = function_coverage_info; + let coverage::FunctionCoverageInfo { body_span, expressions, mappings, .. } = + function_coverage_info; + writeln!(w, "{INDENT}coverage body span: {body_span:?}")?; for (id, expression) in expressions.iter_enumerated() { writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index bc698e9ebf6..39ad1fd23b2 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, Pos, RelativeBytePos, Span, Symbol}; +use rustc_span::{BytePos, Pos, RelativeBytePos, SourceFile, Span}; use tracing::{debug, debug_span, trace}; use crate::coverage::counters::{CounterIncrementSite, CoverageCounters}; @@ -122,6 +122,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { function_source_hash: hir_info.function_source_hash, + body_span: hir_info.body_span, num_counters: coverage_counters.num_counters(), mcdc_bitmap_bits: extracted_mappings.mcdc_bitmap_bits, expressions: coverage_counters.into_expressions(), @@ -142,19 +143,11 @@ fn create_mappings<'tcx>( coverage_counters: &CoverageCounters, ) -> Vec { let source_map = tcx.sess.source_map(); - let body_span = hir_info.body_span; - - let source_file = source_map.lookup_source_file(body_span.lo()); - - use rustc_session::RemapFileNameExt; - use rustc_session::config::RemapPathScopeComponents; - let file_name = Symbol::intern( - &source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(), - ); + let file = source_map.lookup_source_file(hir_info.body_span.lo()); let term_for_bcb = |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); - let region_for_span = |span: Span| make_source_region(source_map, hir_info, file_name, span); + let region_for_span = |span: Span| make_source_region(source_map, hir_info, &file, span); // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { @@ -398,7 +391,7 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb data.statements.insert(0, statement); } -/// Convert the Span into its file name, start line and column, and end line and column. +/// Converts the span into its start line and column, and end line and column. /// /// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by /// the compiler, these column numbers are denoted in **bytes**, because that's what @@ -411,18 +404,12 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb fn make_source_region( source_map: &SourceMap, hir_info: &ExtractedHirInfo, - file_name: Symbol, + file: &SourceFile, span: Span, ) -> Option { let lo = span.lo(); let hi = span.hi(); - let file = source_map.lookup_source_file(lo); - if !file.contains(hi) { - debug!(?span, ?file, ?lo, ?hi, "span crosses multiple files; skipping"); - return None; - } - // Column numbers need to be in bytes, so we can't use the more convenient // `SourceMap` methods for looking up file coordinates. let rpos_and_line_and_byte_column = |pos: BytePos| -> Option<(RelativeBytePos, usize, usize)> { @@ -465,7 +452,6 @@ fn make_source_region( end_line = source_map.doctest_offset_line(&file.name, end_line); check_source_region(SourceRegion { - file_name, start_line: start_line as u32, start_col: start_col as u32, end_line: end_line as u32, @@ -478,7 +464,7 @@ fn make_source_region( /// discard regions that are improperly ordered, or might be interpreted in a /// way that makes them improperly ordered. fn check_source_region(source_region: SourceRegion) -> Option { - let SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = source_region; + let SourceRegion { start_line, start_col, end_line, end_col } = source_region; // Line/column coordinates are supposed to be 1-based. If we ever emit // coordinates of 0, `llvm-cov` might misinterpret them. diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index eeeac70b5b8..cbb11d50f79 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -26,18 +26,19 @@ debug a => _9; } ++ coverage body span: $DIR/branch_match_arms.rs:14:11: 21:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(1), op: Add, rhs: Counter(2) }; + coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Add, rhs: Counter(3) }; + coverage ExpressionId(2) => Expression { lhs: Counter(0), op: Subtract, rhs: Expression(1) }; + coverage ExpressionId(3) => Expression { lhs: Counter(3), op: Add, rhs: Counter(2) }; + coverage ExpressionId(4) => Expression { lhs: Expression(3), op: Add, rhs: Counter(1) }; + coverage ExpressionId(5) => Expression { lhs: Expression(4), op: Add, rhs: Expression(2) }; -+ coverage Code(Counter(0)) => $DIR/branch_match_arms.rs:14:1 - 15:21; -+ coverage Code(Counter(3)) => $DIR/branch_match_arms.rs:16:17 - 16:33; -+ coverage Code(Counter(2)) => $DIR/branch_match_arms.rs:17:17 - 17:33; -+ coverage Code(Counter(1)) => $DIR/branch_match_arms.rs:18:17 - 18:33; -+ coverage Code(Expression(2)) => $DIR/branch_match_arms.rs:19:17 - 19:33; -+ coverage Code(Expression(5)) => $DIR/branch_match_arms.rs:21:1 - 21:2; ++ coverage Code(Counter(0)) => 14:1 - 15:21; ++ coverage Code(Counter(3)) => 16:17 - 16:33; ++ coverage Code(Counter(2)) => 17:17 - 17:33; ++ coverage Code(Counter(1)) => 18:17 - 18:33; ++ coverage Code(Expression(2)) => 19:17 - 19:33; ++ coverage Code(Expression(5)) => 21:1 - 21:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index 01b01ea5c17..2efb1fd0a17 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -4,7 +4,8 @@ fn bar() -> bool { let mut _0: bool; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:19:1 - 21:2; ++ coverage body span: $DIR/instrument_coverage.rs:19:18: 21:2 (#0) ++ coverage Code(Counter(0)) => 19:1 - 21:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index a594c44c316..510aa07f32d 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -7,12 +7,13 @@ let mut _2: bool; let mut _3: !; ++ coverage body span: $DIR/instrument_coverage.rs:10:11: 16:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) }; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:10:1 - 10:11; -+ coverage Code(Expression(0)) => $DIR/instrument_coverage.rs:12:12 - 12:17; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:13:13 - 13:18; -+ coverage Code(Counter(1)) => $DIR/instrument_coverage.rs:14:10 - 14:11; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:16:1 - 16:2; ++ coverage Code(Counter(0)) => 10:1 - 10:11; ++ coverage Code(Expression(0)) => 12:12 - 12:17; ++ coverage Code(Counter(0)) => 13:13 - 13:18; ++ coverage Code(Counter(1)) => 14:10 - 14:11; ++ coverage Code(Counter(0)) => 16:1 - 16:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index efb1559baf5..23cdb3d7717 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -7,12 +7,13 @@ coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0) + coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; - coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1 - 14:36; - coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37 - 14:39; - coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39 - 14:40; - coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:1 - 15:2; - coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8 - 14:36; + coverage Code(Counter(0)) => 13:1 - 14:36; + coverage Code(Expression(0)) => 14:37 - 14:39; + coverage Code(Counter(1)) => 14:39 - 14:40; + coverage Code(Counter(0)) => 15:1 - 15:2; + coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; bb0: { Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index a0fe9a5c05c..f6aa42f3eee 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -7,12 +7,13 @@ coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0) ++ coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1 - 14:36; -+ coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37 - 14:39; -+ coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39 - 14:40; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:1 - 15:2; -+ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8 - 14:36; ++ coverage Code(Counter(0)) => 13:1 - 14:36; ++ coverage Code(Expression(0)) => 14:37 - 14:39; ++ coverage Code(Counter(1)) => 14:39 - 14:40; ++ coverage Code(Counter(0)) => 15:1 - 15:2; ++ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; + bb0: { + Coverage::CounterIncrement(0); -- cgit 1.4.1-3-g733a5 From 3c30fe3423b1e7d92584436493bd8fa6f17e13d0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 5 Nov 2024 21:59:10 +1100 Subject: coverage: Restrict empty-span expansion to only cover `{` and `}` --- compiler/rustc_mir_transform/src/coverage/mod.rs | 70 +++++++++++++--------- compiler/rustc_mir_transform/src/lib.rs | 1 - compiler/rustc_span/src/source_map.rs | 2 +- tests/coverage-run-rustdoc/doctest.coverage | 4 +- tests/coverage/abort.cov-map | 8 +-- tests/coverage/abort.coverage | 4 +- tests/coverage/assert.cov-map | 4 +- tests/coverage/async2.cov-map | 8 +-- tests/coverage/async2.coverage | 4 +- tests/coverage/branch/if.cov-map | 18 +++--- tests/coverage/branch/if.coverage | 4 +- tests/coverage/closure.cov-map | 38 ++++++------ tests/coverage/closure.coverage | 4 +- tests/coverage/closure_bug.cov-map | 10 ++-- tests/coverage/closure_bug.coverage | 8 +-- tests/coverage/conditions.cov-map | 22 +++---- tests/coverage/conditions.coverage | 8 +-- tests/coverage/dead_code.cov-map | 12 ++-- tests/coverage/dead_code.coverage | 2 +- tests/coverage/if.cov-map | 4 +- tests/coverage/if.coverage | 2 +- tests/coverage/if_not.cov-map | 6 +- tests/coverage/inner_items.cov-map | 6 +- tests/coverage/inner_items.coverage | 4 +- tests/coverage/lazy_boolean.cov-map | 8 +-- tests/coverage/lazy_boolean.coverage | 2 +- tests/coverage/loop-break.cov-map | 4 +- tests/coverage/loops_branches.cov-map | 12 ++-- tests/coverage/match_or_pattern.cov-map | 10 ++-- tests/coverage/match_or_pattern.coverage | 8 +-- tests/coverage/mcdc/condition-limit.cov-map | 4 +- tests/coverage/mcdc/if.cov-map | 4 +- tests/coverage/nested_loops.cov-map | 4 +- tests/coverage/overflow.cov-map | 8 +-- tests/coverage/panic_unwind.cov-map | 4 +- tests/coverage/simple_loop.cov-map | 4 +- tests/coverage/simple_loop.coverage | 2 +- tests/coverage/simple_match.cov-map | 4 +- tests/coverage/simple_match.coverage | 2 +- tests/coverage/sort_groups.cov-map | 20 +++---- tests/coverage/sort_groups.coverage | 2 +- tests/coverage/unicode.cov-map | 4 +- tests/coverage/unicode.coverage | 2 +- tests/coverage/unused.cov-map | 12 ++-- tests/coverage/uses_crate.coverage | 2 +- tests/coverage/uses_inline_crate.cov-map | 4 +- tests/coverage/uses_inline_crate.coverage | 4 +- ...nstrument_coverage.main.InstrumentCoverage.diff | 2 +- ..._coverage_cleanup.main.CleanupPostBorrowck.diff | 2 +- ...t_coverage_cleanup.main.InstrumentCoverage.diff | 2 +- 50 files changed, 200 insertions(+), 189 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 39ad1fd23b2..e8b3d80be02 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, Pos, RelativeBytePos, SourceFile, Span}; +use rustc_span::{BytePos, Pos, SourceFile, Span}; use tracing::{debug, debug_span, trace}; use crate::coverage::counters::{CounterIncrementSite, CoverageCounters}; @@ -391,6 +391,41 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb data.statements.insert(0, statement); } +fn ensure_non_empty_span( + source_map: &SourceMap, + hir_info: &ExtractedHirInfo, + span: Span, +) -> Option { + if !span.is_empty() { + return Some(span); + } + + let lo = span.lo(); + let hi = span.hi(); + + // The span is empty, so try to expand it to cover an adjacent '{' or '}', + // but only within the bounds of the body span. + let try_next = hi < hir_info.body_span.hi(); + let try_prev = hir_info.body_span.lo() < lo; + if !(try_next || try_prev) { + return None; + } + + source_map + .span_to_source(span, |src, start, end| try { + // We're only checking for specific ASCII characters, so we don't + // have to worry about multi-byte code points. + if try_next && src.as_bytes()[end] == b'{' { + Some(span.with_hi(hi + BytePos(1))) + } else if try_prev && src.as_bytes()[start - 1] == b'}' { + Some(span.with_lo(lo - BytePos(1))) + } else { + None + } + }) + .ok()? +} + /// Converts the span into its start line and column, and end line and column. /// /// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by @@ -407,44 +442,23 @@ fn make_source_region( file: &SourceFile, span: Span, ) -> Option { + let span = ensure_non_empty_span(source_map, hir_info, span)?; + let lo = span.lo(); let hi = span.hi(); // Column numbers need to be in bytes, so we can't use the more convenient // `SourceMap` methods for looking up file coordinates. - let rpos_and_line_and_byte_column = |pos: BytePos| -> Option<(RelativeBytePos, usize, usize)> { + let line_and_byte_column = |pos: BytePos| -> Option<(usize, usize)> { let rpos = file.relative_position(pos); let line_index = file.lookup_line(rpos)?; let line_start = file.lines()[line_index]; // Line numbers and column numbers are 1-based, so add 1 to each. - Some((rpos, line_index + 1, (rpos - line_start).to_usize() + 1)) + Some((line_index + 1, (rpos - line_start).to_usize() + 1)) }; - let (lo_rpos, mut start_line, mut start_col) = rpos_and_line_and_byte_column(lo)?; - let (hi_rpos, mut end_line, mut end_col) = rpos_and_line_and_byte_column(hi)?; - - // If the span is empty, try to expand it horizontally by one character's - // worth of bytes, so that it is more visible in `llvm-cov` reports. - // We do this after resolving line/column numbers, so that empty spans at the - // end of a line get an extra column instead of wrapping to the next line. - let body_span = hir_info.body_span; - if span.is_empty() - && body_span.contains(span) - && let Some(src) = &file.src - { - // Prefer to expand the end position, if it won't go outside the body span. - if hi < body_span.hi() { - let hi_rpos = hi_rpos.to_usize(); - let nudge_bytes = src.ceil_char_boundary(hi_rpos + 1) - hi_rpos; - end_col += nudge_bytes; - } else if lo > body_span.lo() { - let lo_rpos = lo_rpos.to_usize(); - let nudge_bytes = lo_rpos - src.floor_char_boundary(lo_rpos - 1); - // Subtract the nudge, but don't go below column 1. - start_col = start_col.saturating_sub(nudge_bytes).max(1); - } - // If neither nudge could be applied, stick with the empty span coordinates. - } + let (mut start_line, start_col) = line_and_byte_column(lo)?; + let (mut end_line, end_col) = line_and_byte_column(hi)?; // Apply an offset so that code in doctests has correct line numbers. // FIXME(#79417): Currently we have no way to offset doctest _columns_. diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index d184328748f..e18f66ac0a3 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -9,7 +9,6 @@ #![feature(let_chains)] #![feature(map_try_insert)] #![feature(never_type)] -#![feature(round_char_boundary)] #![feature(try_blocks)] #![feature(yeet_expr)] #![warn(unreachable_pub)] diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index f36bb38623e..e74a5c2d8fe 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -534,7 +534,7 @@ impl SourceMap { /// Extracts the source surrounding the given `Span` using the `extract_source` function. The /// extract function takes three arguments: a string slice containing the source, an index in /// the slice for the beginning of the span and an index in the slice for the end of the span. - fn span_to_source(&self, sp: Span, extract_source: F) -> Result + pub fn span_to_source(&self, sp: Span, extract_source: F) -> Result where F: Fn(&str, usize, usize) -> Result, { diff --git a/tests/coverage-run-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage index 396811c5487..f007eb0cade 100644 --- a/tests/coverage-run-rustdoc/doctest.coverage +++ b/tests/coverage-run-rustdoc/doctest.coverage @@ -45,11 +45,11 @@ $DIR/doctest.rs: LL| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() { LL| 1|//! println!("{:?}", res); LL| 1|//! } - ^0 + ^0 LL| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() { LL| 1|//! res = Ok(1); LL| 1|//! } - ^0 + ^0 LL| 1|//! res = Ok(0); LL| |//! } LL| |//! // need to be explicit because rustdoc cant infer the return type diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map index 06dce43c3ca..c121fa551dc 100644 --- a/tests/coverage/abort.cov-map +++ b/tests/coverage/abort.cov-map @@ -1,5 +1,5 @@ Function name: abort::main -Raw bytes (89): 0x[01, 01, 0a, 01, 27, 05, 09, 03, 0d, 22, 11, 03, 0d, 03, 0d, 22, 15, 03, 0d, 03, 0d, 05, 09, 0d, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 22, 01, 0c, 00, 19, 11, 00, 1a, 02, 0a, 0e, 02, 0a, 00, 0b, 22, 02, 0c, 00, 19, 15, 00, 1a, 00, 31, 1a, 00, 31, 00, 32, 22, 04, 0c, 00, 19, 05, 00, 1a, 00, 31, 09, 00, 31, 00, 32, 27, 01, 09, 00, 17, 0d, 02, 05, 01, 02] +Raw bytes (89): 0x[01, 01, 0a, 01, 27, 05, 09, 03, 0d, 22, 11, 03, 0d, 03, 0d, 22, 15, 03, 0d, 03, 0d, 05, 09, 0d, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 22, 01, 0c, 00, 19, 11, 00, 1a, 02, 0a, 0e, 02, 09, 00, 0a, 22, 02, 0c, 00, 19, 15, 00, 1a, 00, 31, 1a, 00, 30, 00, 31, 22, 04, 0c, 00, 19, 05, 00, 1a, 00, 31, 09, 00, 30, 00, 31, 27, 01, 09, 00, 17, 0d, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 10 @@ -20,17 +20,17 @@ Number of file 0 mappings: 13 - Code(Expression(8, Sub)) at (prev + 1, 12) to (start + 0, 25) = ((c0 + (c1 + c2)) - c3) - Code(Counter(4)) at (prev + 0, 26) to (start + 2, 10) -- Code(Expression(3, Sub)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(3, Sub)) at (prev + 2, 9) to (start + 0, 10) = (((c0 + (c1 + c2)) - c3) - c4) - Code(Expression(8, Sub)) at (prev + 2, 12) to (start + 0, 25) = ((c0 + (c1 + c2)) - c3) - Code(Counter(5)) at (prev + 0, 26) to (start + 0, 49) -- Code(Expression(6, Sub)) at (prev + 0, 49) to (start + 0, 50) +- Code(Expression(6, Sub)) at (prev + 0, 48) to (start + 0, 49) = (((c0 + (c1 + c2)) - c3) - c5) - Code(Expression(8, Sub)) at (prev + 4, 12) to (start + 0, 25) = ((c0 + (c1 + c2)) - c3) - Code(Counter(1)) at (prev + 0, 26) to (start + 0, 49) -- Code(Counter(2)) at (prev + 0, 49) to (start + 0, 50) +- Code(Counter(2)) at (prev + 0, 48) to (start + 0, 49) - Code(Expression(9, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + c2) - Code(Counter(3)) at (prev + 2, 5) to (start + 1, 2) diff --git a/tests/coverage/abort.coverage b/tests/coverage/abort.coverage index 29e3ad5eda7..be3dadab487 100644 --- a/tests/coverage/abort.coverage +++ b/tests/coverage/abort.coverage @@ -18,12 +18,12 @@ LL| 6| } LL| | // See discussion (below the `Notes` section) on coverage results for the closing brace. LL| 10| if countdown < 5 { might_abort(false); } // Counts for different regions on one line. - ^4 ^6 + ^4 ^6 LL| | // For the following example, the closing brace is the last character on the line. LL| | // This shows the character after the closing brace is highlighted, even if that next LL| | // character is a newline. LL| 10| if countdown < 5 { might_abort(false); } - ^4 ^6 + ^4 ^6 LL| 10| countdown -= 1; LL| | } LL| 1| Ok(()) diff --git a/tests/coverage/assert.cov-map b/tests/coverage/assert.cov-map index 018fcc2c3db..b3cec390119 100644 --- a/tests/coverage/assert.cov-map +++ b/tests/coverage/assert.cov-map @@ -1,5 +1,5 @@ Function name: assert::main -Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 09, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] +Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 09, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 09, 00, 0a, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -21,7 +21,7 @@ Number of file 0 mappings: 9 - Code(Expression(4, Sub)) at (prev + 2, 19) to (start + 0, 32) = (((c0 + (c1 + (c2 + c3))) - c4) - c1) - Code(Counter(2)) at (prev + 0, 33) to (start + 2, 10) -- Code(Counter(3)) at (prev + 2, 10) to (start + 0, 11) +- Code(Counter(3)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + (c2 + c3)) - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async2.cov-map index ed61e91efc2..d6462fded13 100644 --- a/tests/coverage/async2.cov-map +++ b/tests/coverage/async2.cov-map @@ -8,14 +8,14 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: async2::async_func::{closure#0} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 10, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 10, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 16, 23) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 @@ -47,14 +47,14 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: async2::non_async_func -Raw bytes (24): 0x[01, 01, 00, 04, 01, 08, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 08, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/async2.coverage b/tests/coverage/async2.coverage index ed9bc4c239d..cdc171180b8 100644 --- a/tests/coverage/async2.coverage +++ b/tests/coverage/async2.coverage @@ -11,7 +11,7 @@ LL| 1| if b { LL| 1| println!("non_async_func println in block"); LL| 1| } - ^0 + ^0 LL| 1|} LL| | LL| 1|async fn async_func() { @@ -20,7 +20,7 @@ LL| 1| if b { LL| 1| println!("async_func println in block"); LL| 1| } - ^0 + ^0 LL| 1|} LL| | LL| 1|async fn async_func_just_println() { diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map index 4a8cb664dd8..0ad78a720a7 100644 --- a/tests/coverage/branch/if.cov-map +++ b/tests/coverage/branch/if.cov-map @@ -25,7 +25,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c4 Function name: if::branch_not -Raw bytes (116): 0x[01, 01, 07, 05, 09, 05, 0d, 05, 0d, 05, 11, 05, 11, 05, 15, 05, 15, 12, 01, 0c, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 09, 01, 09, 00, 11, 02, 01, 06, 00, 07, 05, 01, 08, 00, 0a, 20, 0a, 0d, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 0d, 02, 06, 00, 07, 05, 01, 08, 00, 0b, 20, 11, 12, 00, 08, 00, 0b, 11, 00, 0c, 02, 06, 12, 02, 06, 00, 07, 05, 01, 08, 00, 0c, 20, 1a, 15, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 15, 02, 06, 00, 07, 05, 01, 01, 00, 02] +Raw bytes (116): 0x[01, 01, 07, 05, 09, 05, 0d, 05, 0d, 05, 11, 05, 11, 05, 15, 05, 15, 12, 01, 0c, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 09, 01, 09, 00, 11, 02, 01, 05, 00, 06, 05, 01, 08, 00, 0a, 20, 0a, 0d, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 0d, 02, 05, 00, 06, 05, 01, 08, 00, 0b, 20, 11, 12, 00, 08, 00, 0b, 11, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 05, 01, 08, 00, 0c, 20, 1a, 15, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 15, 02, 05, 00, 06, 05, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -43,7 +43,7 @@ Number of file 0 mappings: 18 true = c2 false = (c1 - c2) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 17) -- Code(Expression(0, Sub)) at (prev + 1, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) = (c1 - c2) - Code(Counter(1)) at (prev + 1, 8) to (start + 0, 10) - Branch { true: Expression(2, Sub), false: Counter(3) } at (prev + 0, 8) to (start + 0, 10) @@ -51,13 +51,13 @@ Number of file 0 mappings: 18 false = c3 - Code(Expression(2, Sub)) at (prev + 0, 11) to (start + 2, 6) = (c1 - c3) -- Code(Counter(3)) at (prev + 2, 6) to (start + 0, 7) +- Code(Counter(3)) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(1)) at (prev + 1, 8) to (start + 0, 11) - Branch { true: Counter(4), false: Expression(4, Sub) } at (prev + 0, 8) to (start + 0, 11) true = c4 false = (c1 - c4) - Code(Counter(4)) at (prev + 0, 12) to (start + 2, 6) -- Code(Expression(4, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(4, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c1 - c4) - Code(Counter(1)) at (prev + 1, 8) to (start + 0, 12) - Branch { true: Expression(6, Sub), false: Counter(5) } at (prev + 0, 8) to (start + 0, 12) @@ -65,12 +65,12 @@ Number of file 0 mappings: 18 false = c5 - Code(Expression(6, Sub)) at (prev + 0, 13) to (start + 2, 6) = (c1 - c5) -- Code(Counter(5)) at (prev + 2, 6) to (start + 0, 7) +- Code(Counter(5)) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c5 Function name: if::branch_not_as -Raw bytes (90): 0x[01, 01, 05, 05, 09, 05, 0d, 05, 0d, 05, 11, 05, 11, 0e, 01, 1d, 01, 01, 10, 05, 03, 08, 00, 14, 20, 02, 09, 00, 08, 00, 14, 02, 00, 15, 02, 06, 09, 02, 06, 00, 07, 05, 01, 08, 00, 15, 20, 0d, 0a, 00, 08, 00, 15, 0d, 00, 16, 02, 06, 0a, 02, 06, 00, 07, 05, 01, 08, 00, 16, 20, 12, 11, 00, 08, 00, 16, 12, 00, 17, 02, 06, 11, 02, 06, 00, 07, 05, 01, 01, 00, 02] +Raw bytes (90): 0x[01, 01, 05, 05, 09, 05, 0d, 05, 0d, 05, 11, 05, 11, 0e, 01, 1d, 01, 01, 10, 05, 03, 08, 00, 14, 20, 02, 09, 00, 08, 00, 14, 02, 00, 15, 02, 06, 09, 02, 05, 00, 06, 05, 01, 08, 00, 15, 20, 0d, 0a, 00, 08, 00, 15, 0d, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 05, 01, 08, 00, 16, 20, 12, 11, 00, 08, 00, 16, 12, 00, 17, 02, 06, 11, 02, 05, 00, 06, 05, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -87,13 +87,13 @@ Number of file 0 mappings: 14 false = c2 - Code(Expression(0, Sub)) at (prev + 0, 21) to (start + 2, 6) = (c1 - c2) -- Code(Counter(2)) at (prev + 2, 6) to (start + 0, 7) +- Code(Counter(2)) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(1)) at (prev + 1, 8) to (start + 0, 21) - Branch { true: Counter(3), false: Expression(2, Sub) } at (prev + 0, 8) to (start + 0, 21) true = c3 false = (c1 - c3) - Code(Counter(3)) at (prev + 0, 22) to (start + 2, 6) -- Code(Expression(2, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(2, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c1 - c3) - Code(Counter(1)) at (prev + 1, 8) to (start + 0, 22) - Branch { true: Expression(4, Sub), false: Counter(4) } at (prev + 0, 8) to (start + 0, 22) @@ -101,7 +101,7 @@ Number of file 0 mappings: 14 false = c4 - Code(Expression(4, Sub)) at (prev + 0, 23) to (start + 2, 6) = (c1 - c4) -- Code(Counter(4)) at (prev + 2, 6) to (start + 0, 7) +- Code(Counter(4)) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c4 diff --git a/tests/coverage/branch/if.coverage b/tests/coverage/branch/if.coverage index 2a9a408b16a..3d107188ca6 100644 --- a/tests/coverage/branch/if.coverage +++ b/tests/coverage/branch/if.coverage @@ -30,7 +30,7 @@ ------------------ LL| 2| say("not not a"); LL| 2| } - ^1 + ^1 LL| 3| if !!!a { ------------------ | Branch (LL:8): [True: 1, False: 2] @@ -54,7 +54,7 @@ ------------------ LL| 2| say("not not (a as bool)"); LL| 2| } - ^1 + ^1 LL| 3| if !!!(a as bool) { ------------------ | Branch (LL:8): [True: 1, False: 2] diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index d50f9f8e7af..adf4aba0c23 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -1,5 +1,5 @@ Function name: closure::main -Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 06, 00, 07, 01, 01, 05, 03, 02] +Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -27,13 +27,13 @@ Number of file 0 mappings: 24 - Code(Counter(0)) at (prev + 8, 9) to (start + 0, 68) - Code(Counter(0)) at (prev + 10, 8) to (start + 0, 16) - Code(Counter(1)) at (prev + 0, 17) to (start + 4, 6) -- Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 3, 2) Highest counter ID seen: c1 Function name: closure::main::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 28, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 01, 01, 09, 01, 06] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 28, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -41,7 +41,7 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 40, 5) to (start + 2, 20) - Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) -- Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) Highest counter ID seen: c1 @@ -83,17 +83,16 @@ Number of file 0 mappings: 1 Highest counter ID seen: (none) Function name: closure::main::{closure#14} -Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, b3, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 01, 0d, 00, 0e] +Raw bytes (22): 0x[01, 01, 01, 01, 05, 03, 01, b3, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 +Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 179, 13) to (start + 2, 27) - Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) Highest counter ID seen: c1 Function name: closure::main::{closure#15} @@ -113,17 +112,16 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: closure::main::{closure#16} -Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, c5, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 01, 0d, 00, 0e] +Raw bytes (22): 0x[01, 01, 01, 01, 05, 03, 01, c5, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 +Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 197, 13) to (start + 2, 27) - Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) Highest counter ID seen: c1 Function name: closure::main::{closure#17} @@ -143,19 +141,19 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: closure::main::{closure#18} (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 0d, 02, 1c, 00, 02, 1d, 02, 12, 00, 02, 12, 00, 13, 00, 01, 11, 01, 0e] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 0d, 02, 1c, 00, 02, 1d, 02, 12, 00, 02, 11, 00, 12, 00, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 - Code(Zero) at (prev + 25, 13) to (start + 2, 28) - Code(Zero) at (prev + 2, 29) to (start + 2, 18) -- Code(Zero) at (prev + 2, 18) to (start + 0, 19) +- Code(Zero) at (prev + 2, 17) to (start + 0, 18) - Code(Zero) at (prev + 1, 17) to (start + 1, 14) Highest counter ID seen: (none) Function name: closure::main::{closure#19} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 01, 01, 11, 01, 0e] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -163,13 +161,13 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 67, 13) to (start + 2, 28) - Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) -- Code(Expression(0, Sub)) at (prev + 2, 18) to (start + 0, 19) +- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 18) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14) Highest counter ID seen: c1 Function name: closure::main::{closure#1} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 52, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 01, 01, 09, 01, 06] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 52, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -177,13 +175,13 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 82, 5) to (start + 2, 20) - Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) -- Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) Highest counter ID seen: c1 Function name: closure::main::{closure#2} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 68, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 01, 01, 09, 01, 06] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 68, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -191,20 +189,20 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 104, 5) to (start + 2, 20) - Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) -- Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) Highest counter ID seen: c1 Function name: closure::main::{closure#3} (unused) -Raw bytes (25): 0x[01, 01, 00, 04, 00, 81, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] +Raw bytes (25): 0x[01, 01, 00, 04, 00, 81, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 09, 00, 0a, 00, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 - Code(Zero) at (prev + 129, 5) to (start + 1, 20) - Code(Zero) at (prev + 1, 21) to (start + 2, 10) -- Code(Zero) at (prev + 2, 10) to (start + 0, 11) +- Code(Zero) at (prev + 2, 9) to (start + 0, 10) - Code(Zero) at (prev + 1, 9) to (start + 1, 6) Highest counter ID seen: (none) diff --git a/tests/coverage/closure.coverage b/tests/coverage/closure.coverage index 2f040b39f88..3eac52eb723 100644 --- a/tests/coverage/closure.coverage +++ b/tests/coverage/closure.coverage @@ -183,7 +183,7 @@ LL| 0| println!( LL| 0| "not called: {}", LL| 0| if is_true { "check" } else { "me" } - LL| 0| ) + LL| | ) LL| | ; LL| | LL| 1| let short_used_not_covered_closure_line_break_block_embedded_branch = @@ -202,7 +202,7 @@ LL| 1| "not called: {}", LL| 1| if is_true { "check" } else { "me" } ^0 - LL| 1| ) + LL| | ) LL| | ; LL| | LL| 1| let short_used_covered_closure_line_break_block_embedded_branch = diff --git a/tests/coverage/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map index 96e1e339e56..40a8bdf9c1d 100644 --- a/tests/coverage/closure_bug.cov-map +++ b/tests/coverage/closure_bug.cov-map @@ -1,5 +1,5 @@ Function name: closure_bug::main -Raw bytes (97): 0x[01, 01, 04, 01, 05, 01, 09, 01, 0d, 01, 11, 11, 01, 07, 01, 03, 0a, 01, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, 02, 00, 17, 00, 18, 01, 02, 09, 00, 0a, 01, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, 06, 00, 17, 00, 18, 01, 02, 09, 00, 0a, 01, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, 0a, 00, 17, 00, 18, 01, 02, 09, 00, 0a, 01, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, 0e, 00, 17, 00, 18, 01, 01, 01, 00, 02] +Raw bytes (97): 0x[01, 01, 04, 01, 05, 01, 09, 01, 0d, 01, 11, 11, 01, 07, 01, 03, 0a, 01, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, 02, 00, 16, 00, 17, 01, 02, 09, 00, 0a, 01, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, 06, 00, 16, 00, 17, 01, 02, 09, 00, 0a, 01, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, 0a, 00, 16, 00, 17, 01, 02, 09, 00, 0a, 01, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, 0e, 00, 16, 00, 17, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -11,22 +11,22 @@ Number of file 0 mappings: 17 - Code(Counter(0)) at (prev + 7, 1) to (start + 3, 10) - Code(Counter(0)) at (prev + 9, 5) to (start + 1, 14) - Code(Counter(1)) at (prev + 1, 15) to (start + 0, 23) -- Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 0, 24) +- Code(Expression(0, Sub)) at (prev + 0, 22) to (start + 0, 23) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 6, 5) to (start + 1, 14) - Code(Counter(2)) at (prev + 1, 15) to (start + 0, 23) -- Code(Expression(1, Sub)) at (prev + 0, 23) to (start + 0, 24) +- Code(Expression(1, Sub)) at (prev + 0, 22) to (start + 0, 23) = (c0 - c2) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 6, 5) to (start + 1, 14) - Code(Counter(3)) at (prev + 1, 15) to (start + 0, 23) -- Code(Expression(2, Sub)) at (prev + 0, 23) to (start + 0, 24) +- Code(Expression(2, Sub)) at (prev + 0, 22) to (start + 0, 23) = (c0 - c3) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 6, 5) to (start + 1, 14) - Code(Counter(4)) at (prev + 1, 15) to (start + 0, 23) -- Code(Expression(3, Sub)) at (prev + 0, 23) to (start + 0, 24) +- Code(Expression(3, Sub)) at (prev + 0, 22) to (start + 0, 23) = (c0 - c4) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c4 diff --git a/tests/coverage/closure_bug.coverage b/tests/coverage/closure_bug.coverage index 3bf19f28072..cc64470baa7 100644 --- a/tests/coverage/closure_bug.coverage +++ b/tests/coverage/closure_bug.coverage @@ -16,7 +16,7 @@ LL| | LL| 1| a(); LL| 1| if truthy { a(); } - ^0 + ^0 LL| | LL| 1| let b LL| | = @@ -27,7 +27,7 @@ LL| | LL| 1| b(); LL| 1| if truthy { b(); } - ^0 + ^0 LL| | LL| 1| let c LL| | = @@ -38,7 +38,7 @@ LL| | LL| 1| c(); LL| 1| if truthy { c(); } - ^0 + ^0 LL| | LL| 1| let d LL| | = @@ -49,6 +49,6 @@ LL| | LL| 1| d(); LL| 1| if truthy { d(); } - ^0 + ^0 LL| 1|} diff --git a/tests/coverage/conditions.cov-map b/tests/coverage/conditions.cov-map index a392d1b7028..938e4404013 100644 --- a/tests/coverage/conditions.cov-map +++ b/tests/coverage/conditions.cov-map @@ -1,5 +1,5 @@ Function name: conditions::main -Raw bytes (799): 0x[01, 01, 94, 01, 09, 2b, 2f, 41, 33, 3d, 35, 39, 01, 09, 0d, 35, 1e, 39, 0d, 35, 33, 3d, 35, 39, 2f, 41, 33, 3d, 35, 39, ce, 04, 0d, 01, 09, 03, 49, 62, 31, 03, 49, 5e, 4d, 62, 31, 03, 49, 5a, 51, 5e, 4d, 62, 31, 03, 49, 87, 01, 55, 4d, 51, 83, 01, 59, 87, 01, 55, 4d, 51, 49, 7f, 83, 01, 59, 87, 01, 55, 4d, 51, 5d, 65, ae, 01, 2d, 5d, 65, aa, 01, 69, ae, 01, 2d, 5d, 65, a6, 01, 6d, aa, 01, 69, ae, 01, 2d, 5d, 65, f3, 02, 71, 69, 6d, ef, 02, 75, f3, 02, 71, 69, 6d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, de, 02, 29, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, da, 02, 81, 01, de, 02, 29, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, d6, 02, 85, 01, da, 02, 81, 01, de, 02, 29, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, 8f, 04, 89, 01, 81, 01, 85, 01, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, 11, af, 04, b3, 04, 21, b7, 04, 1d, 15, 19, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, fe, 03, 25, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, fa, 03, 15, fe, 03, 25, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, f6, 03, 19, fa, 03, 15, fe, 03, 25, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, b7, 04, 1d, 15, 19, b3, 04, 21, b7, 04, 1d, 15, 19, ab, 04, bb, 04, 11, af, 04, b3, 04, 21, b7, 04, 1d, 15, 19, bf, 04, ca, 04, c3, 04, 31, c7, 04, 2d, 25, 29, ce, 04, 0d, 01, 09, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, 01, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, ce, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 1e, 00, 1d, 00, 2a, 1a, 00, 2e, 00, 3c, 2f, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 2b, 01, 09, 01, 12, ca, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 02, 08, 00, 15, 49, 00, 16, 02, 06, 62, 02, 0f, 00, 1c, 5e, 01, 0c, 00, 19, 5a, 00, 1d, 00, 2a, 56, 00, 2e, 00, 3c, 83, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, 7f, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 7b, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, 5d, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, ae, 01, 04, 11, 00, 1e, aa, 01, 01, 10, 00, 1d, a6, 01, 00, 21, 00, 2e, a2, 01, 00, 32, 00, 40, ef, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, eb, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, e3, 02, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 83, 04, 02, 09, 00, 0a, e3, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, de, 02, 02, 0f, 00, 1c, da, 02, 01, 0c, 00, 19, d6, 02, 00, 1d, 00, 2a, d2, 02, 00, 2e, 00, 3c, 8b, 04, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, 87, 04, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, ab, 04, 05, 09, 00, 0a, 83, 04, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, fe, 03, 02, 0f, 00, 1c, fa, 03, 01, 0c, 00, 19, f6, 03, 00, 1d, 00, 2a, f2, 03, 00, 2e, 00, 3c, b3, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, af, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, a7, 04, 02, 01, 00, 02] +Raw bytes (799): 0x[01, 01, 94, 01, 09, 2b, 2f, 41, 33, 3d, 35, 39, 01, 09, 0d, 35, 1e, 39, 0d, 35, 33, 3d, 35, 39, 2f, 41, 33, 3d, 35, 39, ce, 04, 0d, 01, 09, 03, 49, 62, 31, 03, 49, 5e, 4d, 62, 31, 03, 49, 5a, 51, 5e, 4d, 62, 31, 03, 49, 87, 01, 55, 4d, 51, 83, 01, 59, 87, 01, 55, 4d, 51, 49, 7f, 83, 01, 59, 87, 01, 55, 4d, 51, 5d, 65, ae, 01, 2d, 5d, 65, aa, 01, 69, ae, 01, 2d, 5d, 65, a6, 01, 6d, aa, 01, 69, ae, 01, 2d, 5d, 65, f3, 02, 71, 69, 6d, ef, 02, 75, f3, 02, 71, 69, 6d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, de, 02, 29, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, da, 02, 81, 01, de, 02, 29, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, d6, 02, 85, 01, da, 02, 81, 01, de, 02, 29, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, 8f, 04, 89, 01, 81, 01, 85, 01, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, 11, af, 04, b3, 04, 21, b7, 04, 1d, 15, 19, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, fe, 03, 25, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, fa, 03, 15, fe, 03, 25, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, f6, 03, 19, fa, 03, 15, fe, 03, 25, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, b7, 04, 1d, 15, 19, b3, 04, 21, b7, 04, 1d, 15, 19, ab, 04, bb, 04, 11, af, 04, b3, 04, 21, b7, 04, 1d, 15, 19, bf, 04, ca, 04, c3, 04, 31, c7, 04, 2d, 25, 29, ce, 04, 0d, 01, 09, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 03, 09, 00, 0a, 01, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, ce, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 1e, 00, 1d, 00, 2a, 1a, 00, 2e, 00, 3c, 2f, 00, 3d, 02, 0a, 41, 02, 09, 00, 0a, 2b, 01, 09, 01, 12, ca, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 02, 08, 00, 15, 49, 00, 16, 02, 06, 62, 02, 0f, 00, 1c, 5e, 01, 0c, 00, 19, 5a, 00, 1d, 00, 2a, 56, 00, 2e, 00, 3c, 83, 01, 00, 3d, 02, 0a, 59, 02, 09, 00, 0a, 7f, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 7b, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 09, 00, 0a, 5d, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, ae, 01, 04, 11, 00, 1e, aa, 01, 01, 10, 00, 1d, a6, 01, 00, 21, 00, 2e, a2, 01, 00, 32, 00, 40, ef, 02, 00, 41, 02, 0e, 75, 02, 0d, 00, 0e, eb, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 05, 00, 06, e3, 02, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 05, 00, 06, 83, 04, 02, 09, 00, 0a, e3, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, de, 02, 02, 0f, 00, 1c, da, 02, 01, 0c, 00, 19, d6, 02, 00, 1d, 00, 2a, d2, 02, 00, 2e, 00, 3c, 8b, 04, 00, 3d, 02, 0a, 8d, 01, 02, 09, 00, 0a, 87, 04, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, ab, 04, 05, 09, 00, 0a, 83, 04, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, fe, 03, 02, 0f, 00, 1c, fa, 03, 01, 0c, 00, 19, f6, 03, 00, 1d, 00, 2a, f2, 03, 00, 2e, 00, 3c, b3, 04, 00, 3d, 02, 0a, 21, 02, 09, 00, 0a, af, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, a7, 04, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 148 @@ -154,7 +154,7 @@ Number of expressions: 148 Number of file 0 mappings: 68 - Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) - Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 10) = (c2 + (((c13 + c14) + c15) + c16)) - Code(Counter(0)) at (prev + 0, 16) to (start + 0, 29) @@ -168,7 +168,7 @@ Number of file 0 mappings: 68 = ((c3 - c13) - c14) - Code(Expression(11, Add)) at (prev + 0, 61) to (start + 2, 10) = ((c13 + c14) + c15) -- Code(Counter(16)) at (prev + 2, 10) to (start + 0, 11) +- Code(Counter(16)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(10, Add)) at (prev + 1, 9) to (start + 1, 18) = (((c13 + c14) + c15) + c16) - Code(Expression(146, Sub)) at (prev + 3, 9) to (start + 0, 15) @@ -176,7 +176,7 @@ Number of file 0 mappings: 68 - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 1, 12) = (c2 + (((c13 + c14) + c15) + c16)) - Code(Counter(17)) at (prev + 1, 13) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Expression(0, Add)) at (prev + 2, 8) to (start + 0, 21) = (c2 + (((c13 + c14) + c15) + c16)) - Code(Counter(18)) at (prev + 0, 22) to (start + 2, 6) @@ -190,7 +190,7 @@ Number of file 0 mappings: 68 = (((((c2 + (((c13 + c14) + c15) + c16)) - c18) - c12) - c19) - c20) - Code(Expression(32, Add)) at (prev + 0, 61) to (start + 2, 10) = ((c19 + c20) + c21) -- Code(Counter(22)) at (prev + 2, 10) to (start + 0, 11) +- Code(Counter(22)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(31, Add)) at (prev + 1, 9) to (start + 0, 23) = (((c19 + c20) + c21) + c22) - Code(Counter(12)) at (prev + 2, 9) to (start + 0, 15) @@ -198,7 +198,7 @@ Number of file 0 mappings: 68 = (c18 + (((c19 + c20) + c21) + c22)) - Code(Counter(23)) at (prev + 1, 13) to (start + 1, 16) - Code(Counter(24)) at (prev + 1, 17) to (start + 2, 10) -- Code(Zero) at (prev + 2, 10) to (start + 0, 11) +- Code(Zero) at (prev + 2, 9) to (start + 0, 10) - Code(Counter(23)) at (prev + 2, 12) to (start + 0, 25) - Code(Counter(25)) at (prev + 0, 26) to (start + 2, 10) - Code(Expression(43, Sub)) at (prev + 4, 17) to (start + 0, 30) @@ -211,15 +211,15 @@ Number of file 0 mappings: 68 = ((((c23 - c25) - c11) - c26) - c27) - Code(Expression(91, Add)) at (prev + 0, 65) to (start + 2, 14) = ((c26 + c27) + c28) -- Code(Counter(29)) at (prev + 2, 14) to (start + 0, 15) +- Code(Counter(29)) at (prev + 2, 13) to (start + 0, 14) - Code(Expression(90, Add)) at (prev + 1, 13) to (start + 0, 27) = (((c26 + c27) + c28) + c29) - Code(Counter(11)) at (prev + 2, 13) to (start + 0, 19) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Expression(88, Add)) at (prev + 2, 9) to (start + 1, 12) = ((c25 + (((c26 + c27) + c28) + c29)) + Zero) - Code(Counter(30)) at (prev + 1, 13) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Expression(128, Add)) at (prev + 2, 9) to (start + 0, 10) = (c31 + (((c32 + c33) + c34) + c35)) - Code(Expression(88, Add)) at (prev + 0, 16) to (start + 0, 29) @@ -235,7 +235,7 @@ Number of file 0 mappings: 68 = ((((((c25 + (((c26 + c27) + c28) + c29)) + Zero) - c31) - c10) - c32) - c33) - Code(Expression(130, Add)) at (prev + 0, 61) to (start + 2, 10) = ((c32 + c33) + c34) -- Code(Counter(35)) at (prev + 2, 10) to (start + 0, 11) +- Code(Counter(35)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(129, Add)) at (prev + 1, 9) to (start + 0, 23) = (((c32 + c33) + c34) + c35) - Code(Counter(10)) at (prev + 2, 13) to (start + 2, 15) @@ -254,7 +254,7 @@ Number of file 0 mappings: 68 = (((((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) - c5) - c6) - Code(Expression(140, Add)) at (prev + 0, 61) to (start + 2, 10) = ((c5 + c6) + c7) -- Code(Counter(8)) at (prev + 2, 10) to (start + 0, 11) +- Code(Counter(8)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(139, Add)) at (prev + 1, 9) to (start + 0, 23) = (((c5 + c6) + c7) + c8) - Code(Counter(9)) at (prev + 2, 9) to (start + 0, 15) diff --git a/tests/coverage/conditions.coverage b/tests/coverage/conditions.coverage index 48516217592..83944d37c98 100644 --- a/tests/coverage/conditions.coverage +++ b/tests/coverage/conditions.coverage @@ -5,7 +5,7 @@ LL| 1| if true { LL| 1| countdown = 10; LL| 1| } - ^0 + ^0 LL| | LL| | const B: u32 = 100; LL| 1| let x = if countdown > 7 { @@ -25,7 +25,7 @@ LL| 1| if true { LL| 1| countdown = 10; LL| 1| } - ^0 + ^0 LL| | LL| 1| if countdown > 7 { LL| 1| countdown -= 4; @@ -44,7 +44,7 @@ LL| 1| if true { LL| 1| countdown = 10; LL| 1| } - ^0 + ^0 LL| | LL| 1| if countdown > 7 { LL| 1| countdown -= 4; @@ -64,7 +64,7 @@ LL| 1| if true { LL| 1| countdown = 1; LL| 1| } - ^0 + ^0 LL| | LL| 1| let z = if countdown > 7 { ^0 diff --git a/tests/coverage/dead_code.cov-map b/tests/coverage/dead_code.cov-map index b94c6e656ab..897372fe0b5 100644 --- a/tests/coverage/dead_code.cov-map +++ b/tests/coverage/dead_code.cov-map @@ -1,5 +1,5 @@ Function name: dead_code::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 1b, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 1b, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -7,32 +7,32 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 27, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: dead_code::unused_fn (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 - Code(Zero) at (prev + 15, 1) to (start + 7, 15) - Code(Zero) at (prev + 7, 16) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: dead_code::unused_pub_fn_not_in_library (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 - Code(Zero) at (prev + 3, 1) to (start + 7, 15) - Code(Zero) at (prev + 7, 16) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) diff --git a/tests/coverage/dead_code.coverage b/tests/coverage/dead_code.coverage index c4ee9f23f08..55d196f8160 100644 --- a/tests/coverage/dead_code.coverage +++ b/tests/coverage/dead_code.coverage @@ -34,6 +34,6 @@ LL| 1| if is_true { LL| 1| countdown = 10; LL| 1| } - ^0 + ^0 LL| 1|} diff --git a/tests/coverage/if.cov-map b/tests/coverage/if.cov-map index 8f12afac027..a77ba8194a4 100644 --- a/tests/coverage/if.cov-map +++ b/tests/coverage/if.cov-map @@ -1,5 +1,5 @@ Function name: if::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 04, 01, 12, 10, 05, 13, 05, 05, 06, 02, 05, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 04, 01, 12, 10, 05, 13, 05, 05, 06, 02, 05, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -7,7 +7,7 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 4, 1) to (start + 18, 16) - Code(Counter(1)) at (prev + 19, 5) to (start + 5, 6) -- Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 5, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/if.coverage b/tests/coverage/if.coverage index 77db24ef51b..0762418347c 100644 --- a/tests/coverage/if.coverage +++ b/tests/coverage/if.coverage @@ -26,6 +26,6 @@ LL| 1| 10 LL| 1| ; LL| 1| } - ^0 + ^0 LL| 1|} diff --git a/tests/coverage/if_not.cov-map b/tests/coverage/if_not.cov-map index a2c276b7bb7..f47139ce5a4 100644 --- a/tests/coverage/if_not.cov-map +++ b/tests/coverage/if_not.cov-map @@ -1,5 +1,5 @@ Function name: if_not::if_not -Raw bytes (60): 0x[01, 01, 03, 01, 05, 01, 09, 01, 0d, 0a, 01, 05, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 06, 00, 07, 01, 03, 09, 01, 0d, 06, 02, 05, 02, 06, 09, 02, 06, 00, 07, 01, 03, 09, 01, 0d, 0a, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (60): 0x[01, 01, 03, 01, 05, 01, 09, 01, 0d, 0a, 01, 05, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 05, 00, 06, 01, 03, 09, 01, 0d, 06, 02, 05, 02, 06, 09, 02, 05, 00, 06, 01, 03, 09, 01, 0d, 0a, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -10,11 +10,11 @@ Number of file 0 mappings: 10 - Code(Counter(0)) at (prev + 5, 1) to (start + 3, 13) - Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 2, 6) = (c0 - c1) -- Code(Counter(1)) at (prev + 2, 6) to (start + 0, 7) +- Code(Counter(1)) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 13) - Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 2, 6) = (c0 - c2) -- Code(Counter(2)) at (prev + 2, 6) to (start + 0, 7) +- Code(Counter(2)) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 13) - Code(Expression(2, Sub)) at (prev + 2, 5) to (start + 2, 6) = (c0 - c3) diff --git a/tests/coverage/inner_items.cov-map b/tests/coverage/inner_items.cov-map index 16e86b2cade..a12cce25b64 100644 --- a/tests/coverage/inner_items.cov-map +++ b/tests/coverage/inner_items.cov-map @@ -17,7 +17,7 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: inner_items::main -Raw bytes (43): 0x[01, 01, 02, 01, 05, 01, 09, 07, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 01, 24, 08, 00, 0f, 09, 00, 10, 02, 06, 06, 02, 06, 00, 07, 01, 02, 09, 05, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 01, 09, 07, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 05, 00, 06, 01, 24, 08, 00, 0f, 09, 00, 10, 02, 06, 06, 02, 05, 00, 06, 01, 02, 09, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -26,11 +26,11 @@ Number of expressions: 2 Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 36, 8) to (start + 0, 15) - Code(Counter(2)) at (prev + 0, 16) to (start + 2, 6) -- Code(Expression(1, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c2) - Code(Counter(0)) at (prev + 2, 9) to (start + 5, 2) Highest counter ID seen: c2 diff --git a/tests/coverage/inner_items.coverage b/tests/coverage/inner_items.coverage index 152f3da1a22..8244d347b59 100644 --- a/tests/coverage/inner_items.coverage +++ b/tests/coverage/inner_items.coverage @@ -10,7 +10,7 @@ LL| 1| if is_true { LL| 1| countdown = 10; LL| 1| } - ^0 + ^0 LL| | LL| | mod in_mod { LL| | const IN_MOD_CONST: u32 = 1000; @@ -49,7 +49,7 @@ LL| 1| if is_true { LL| 1| in_func(countdown); LL| 1| } - ^0 + ^0 LL| | LL| 1| let mut val = InStruct { LL| 1| in_struct_field: 101, // diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map index fcb9d8f1ff5..b0c2d736573 100644 --- a/tests/coverage/lazy_boolean.cov-map +++ b/tests/coverage/lazy_boolean.cov-map @@ -1,5 +1,5 @@ Function name: lazy_boolean::main -Raw bytes (158): 0x[01, 01, 07, 01, 05, 01, 09, 01, 0d, 01, 19, 01, 1d, 01, 21, 01, 25, 1c, 01, 04, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 01, 02, 09, 00, 11, 01, 02, 0d, 00, 12, 06, 02, 0d, 00, 12, 01, 03, 09, 00, 11, 01, 02, 0d, 00, 12, 0a, 02, 0d, 00, 12, 01, 02, 09, 00, 11, 01, 00, 14, 00, 19, 11, 00, 1d, 00, 22, 01, 01, 09, 00, 11, 01, 00, 14, 00, 19, 15, 00, 1d, 00, 22, 01, 03, 09, 01, 10, 0e, 02, 05, 03, 06, 19, 03, 06, 00, 07, 01, 03, 09, 00, 10, 1d, 01, 05, 03, 06, 12, 05, 05, 03, 06, 01, 05, 08, 00, 10, 16, 00, 11, 02, 06, 21, 02, 06, 00, 07, 01, 02, 08, 00, 0f, 25, 00, 10, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (158): 0x[01, 01, 07, 01, 05, 01, 09, 01, 0d, 01, 19, 01, 1d, 01, 21, 01, 25, 1c, 01, 04, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 05, 00, 06, 01, 02, 09, 00, 11, 01, 02, 0d, 00, 12, 06, 02, 0d, 00, 12, 01, 03, 09, 00, 11, 01, 02, 0d, 00, 12, 0a, 02, 0d, 00, 12, 01, 02, 09, 00, 11, 01, 00, 14, 00, 19, 11, 00, 1d, 00, 22, 01, 01, 09, 00, 11, 01, 00, 14, 00, 19, 15, 00, 1d, 00, 22, 01, 03, 09, 01, 10, 0e, 02, 05, 03, 06, 19, 03, 05, 00, 06, 01, 03, 09, 00, 10, 1d, 01, 05, 03, 06, 12, 05, 05, 03, 06, 01, 05, 08, 00, 10, 16, 00, 11, 02, 06, 21, 02, 05, 00, 06, 01, 02, 08, 00, 0f, 25, 00, 10, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -13,7 +13,7 @@ Number of expressions: 7 Number of file 0 mappings: 28 - Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 4, 6) -- Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 17) - Code(Counter(0)) at (prev + 2, 13) to (start + 0, 18) @@ -32,7 +32,7 @@ Number of file 0 mappings: 28 - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 16) - Code(Expression(3, Sub)) at (prev + 2, 5) to (start + 3, 6) = (c0 - c6) -- Code(Counter(6)) at (prev + 3, 6) to (start + 0, 7) +- Code(Counter(6)) at (prev + 3, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 16) - Code(Counter(7)) at (prev + 1, 5) to (start + 3, 6) - Code(Expression(4, Sub)) at (prev + 5, 5) to (start + 3, 6) @@ -40,7 +40,7 @@ Number of file 0 mappings: 28 - Code(Counter(0)) at (prev + 5, 8) to (start + 0, 16) - Code(Expression(5, Sub)) at (prev + 0, 17) to (start + 2, 6) = (c0 - c8) -- Code(Counter(8)) at (prev + 2, 6) to (start + 0, 7) +- Code(Counter(8)) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 2, 8) to (start + 0, 15) - Code(Counter(9)) at (prev + 0, 16) to (start + 2, 6) - Code(Expression(6, Sub)) at (prev + 2, 12) to (start + 2, 6) diff --git a/tests/coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage index f058be83900..828ba2a5811 100644 --- a/tests/coverage/lazy_boolean.coverage +++ b/tests/coverage/lazy_boolean.coverage @@ -13,7 +13,7 @@ LL| 1| b = 10; LL| 1| c = 100; LL| 1| } - ^0 + ^0 LL| | let LL| 1| somebool LL| | = diff --git a/tests/coverage/loop-break.cov-map b/tests/coverage/loop-break.cov-map index 63280a0bf7c..0b4c42a43da 100644 --- a/tests/coverage/loop-break.cov-map +++ b/tests/coverage/loop-break.cov-map @@ -1,5 +1,5 @@ Function name: loop_break::main -Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 03, 01, 00, 0b, 03, 02, 0c, 00, 27, 01, 01, 0d, 00, 12, 05, 01, 0a, 00, 0b, 01, 02, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 03, 01, 00, 0b, 03, 02, 0c, 00, 27, 01, 01, 0d, 00, 12, 05, 01, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -9,7 +9,7 @@ Number of file 0 mappings: 5 - Code(Expression(0, Add)) at (prev + 2, 12) to (start + 0, 39) = (c0 + c1) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18) -- Code(Counter(1)) at (prev + 1, 10) to (start + 0, 11) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map index 1d263611a3a..61a6bda676a 100644 --- a/tests/coverage/loops_branches.cov-map +++ b/tests/coverage/loops_branches.cov-map @@ -1,5 +1,5 @@ Function name: ::fmt -Raw bytes (228): 0x[01, 01, 2a, 05, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, a3, 01, a7, 01, 0d, 00, 11, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 96, 01, 00, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 96, 01, 11, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 8f, 01, 19, 25, 92, 01, 96, 01, 11, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0e, 00, 0f, 05, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 9a, 01, 03, 0d, 00, 0e, 9f, 01, 00, 12, 00, 17, 9a, 01, 01, 10, 00, 14, 96, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 46, 01, 12, 00, 13, 96, 01, 01, 11, 00, 22, 92, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 8b, 01, 01, 05, 00, 06] +Raw bytes (228): 0x[01, 01, 2a, 05, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, a3, 01, a7, 01, 0d, 00, 11, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 96, 01, 00, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 96, 01, 11, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 8f, 01, 19, 25, 92, 01, 96, 01, 11, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0d, 00, 0e, 05, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 9a, 01, 03, 0d, 00, 0e, 9f, 01, 00, 12, 00, 17, 9a, 01, 01, 10, 00, 14, 96, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 46, 01, 11, 00, 12, 96, 01, 01, 11, 00, 22, 92, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 8b, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 42 @@ -50,7 +50,7 @@ Number of file 0 mappings: 20 - Code(Counter(1)) at (prev + 2, 16) to (start + 0, 21) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) -- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 14) = (c1 - Zero) - Code(Counter(1)) at (prev + 1, 13) to (start + 0, 30) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) @@ -65,7 +65,7 @@ Number of file 0 mappings: 20 = ((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(17, Sub)) at (prev + 1, 18) to (start + 0, 19) +- Code(Expression(17, Sub)) at (prev + 1, 17) to (start + 0, 18) = (((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) - Zero) - Code(Expression(37, Sub)) at (prev + 1, 17) to (start + 0, 34) = ((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) @@ -78,7 +78,7 @@ Number of file 0 mappings: 20 Highest counter ID seen: c9 Function name: ::fmt -Raw bytes (230): 0x[01, 01, 2b, 01, 00, 02, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, a7, 01, ab, 01, 00, 0d, 00, 15, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 00, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 93, 01, 25, 96, 01, 19, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 06, 01, 0e, 00, 0f, 02, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 9e, 01, 02, 0d, 00, 0e, a3, 01, 00, 12, 00, 17, 9e, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 9a, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 4a, 01, 12, 00, 13, 9a, 01, 01, 11, 00, 22, 96, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, 8f, 01, 01, 05, 00, 06] +Raw bytes (230): 0x[01, 01, 2b, 01, 00, 02, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, a7, 01, ab, 01, 00, 0d, 00, 15, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 00, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 93, 01, 25, 96, 01, 19, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 06, 01, 0d, 00, 0e, 02, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 9e, 01, 02, 0d, 00, 0e, a3, 01, 00, 12, 00, 17, 9e, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 9a, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 4a, 01, 11, 00, 12, 9a, 01, 01, 11, 00, 22, 96, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, 8f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 43 @@ -132,7 +132,7 @@ Number of file 0 mappings: 20 = (c0 - Zero) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) -- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 15) +- Code(Expression(1, Sub)) at (prev + 1, 13) to (start + 0, 14) = ((c0 - Zero) - Zero) - Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 30) = (c0 - Zero) @@ -148,7 +148,7 @@ Number of file 0 mappings: 20 = ((((Zero + c3) + (Zero + c5)) - c6) - Zero) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(18, Sub)) at (prev + 1, 18) to (start + 0, 19) +- Code(Expression(18, Sub)) at (prev + 1, 17) to (start + 0, 18) = (((((Zero + c3) + (Zero + c5)) - c6) - Zero) - Zero) - Code(Expression(38, Sub)) at (prev + 1, 17) to (start + 0, 34) = ((((Zero + c3) + (Zero + c5)) - c6) - Zero) diff --git a/tests/coverage/match_or_pattern.cov-map b/tests/coverage/match_or_pattern.cov-map index f6491ea262d..2beb327bc05 100644 --- a/tests/coverage/match_or_pattern.cov-map +++ b/tests/coverage/match_or_pattern.cov-map @@ -1,5 +1,5 @@ Function name: match_or_pattern::main -Raw bytes (185): 0x[01, 01, 1c, 01, 05, 09, 0d, 23, 11, 09, 0d, 1f, 15, 23, 11, 09, 0d, 23, 11, 09, 0d, 19, 1d, 43, 21, 19, 1d, 3f, 25, 43, 21, 19, 1d, 43, 21, 19, 1d, 29, 2d, 63, 31, 29, 2d, 5f, 35, 63, 31, 29, 2d, 63, 31, 29, 2d, 39, 3d, 6f, 41, 39, 3d, 19, 01, 01, 01, 08, 0f, 05, 08, 10, 03, 06, 02, 03, 06, 00, 07, 01, 01, 0b, 00, 11, 11, 03, 1b, 00, 1d, 23, 01, 0e, 00, 10, 1f, 02, 08, 00, 0f, 15, 00, 10, 03, 06, 12, 03, 06, 00, 07, 1f, 01, 0b, 00, 11, 21, 01, 1b, 00, 1d, 43, 01, 0e, 00, 10, 3f, 02, 08, 00, 0f, 25, 00, 10, 03, 06, 32, 03, 06, 00, 07, 3f, 01, 0b, 00, 11, 31, 01, 1b, 00, 1d, 63, 01, 0e, 00, 10, 5f, 02, 08, 00, 0f, 35, 00, 10, 03, 06, 52, 03, 06, 00, 07, 5f, 01, 0b, 00, 11, 41, 01, 1b, 00, 1d, 6f, 01, 0e, 00, 10, 6b, 02, 01, 00, 02] +Raw bytes (185): 0x[01, 01, 1c, 01, 05, 09, 0d, 23, 11, 09, 0d, 1f, 15, 23, 11, 09, 0d, 23, 11, 09, 0d, 19, 1d, 43, 21, 19, 1d, 3f, 25, 43, 21, 19, 1d, 43, 21, 19, 1d, 29, 2d, 63, 31, 29, 2d, 5f, 35, 63, 31, 29, 2d, 63, 31, 29, 2d, 39, 3d, 6f, 41, 39, 3d, 19, 01, 01, 01, 08, 0f, 05, 08, 10, 03, 06, 02, 03, 05, 00, 06, 01, 01, 0b, 00, 11, 11, 03, 1b, 00, 1d, 23, 01, 0e, 00, 10, 1f, 02, 08, 00, 0f, 15, 00, 10, 03, 06, 12, 03, 05, 00, 06, 1f, 01, 0b, 00, 11, 21, 01, 1b, 00, 1d, 43, 01, 0e, 00, 10, 3f, 02, 08, 00, 0f, 25, 00, 10, 03, 06, 32, 03, 05, 00, 06, 3f, 01, 0b, 00, 11, 31, 01, 1b, 00, 1d, 63, 01, 0e, 00, 10, 5f, 02, 08, 00, 0f, 35, 00, 10, 03, 06, 52, 03, 05, 00, 06, 5f, 01, 0b, 00, 11, 41, 01, 1b, 00, 1d, 6f, 01, 0e, 00, 10, 6b, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 28 @@ -34,7 +34,7 @@ Number of expressions: 28 Number of file 0 mappings: 25 - Code(Counter(0)) at (prev + 1, 1) to (start + 8, 15) - Code(Counter(1)) at (prev + 8, 16) to (start + 3, 6) -- Code(Expression(0, Sub)) at (prev + 3, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 3, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 11) to (start + 0, 17) - Code(Counter(4)) at (prev + 3, 27) to (start + 0, 29) @@ -43,7 +43,7 @@ Number of file 0 mappings: 25 - Code(Expression(7, Add)) at (prev + 2, 8) to (start + 0, 15) = ((c2 + c3) + c4) - Code(Counter(5)) at (prev + 0, 16) to (start + 3, 6) -- Code(Expression(4, Sub)) at (prev + 3, 6) to (start + 0, 7) +- Code(Expression(4, Sub)) at (prev + 3, 5) to (start + 0, 6) = (((c2 + c3) + c4) - c5) - Code(Expression(7, Add)) at (prev + 1, 11) to (start + 0, 17) = ((c2 + c3) + c4) @@ -53,7 +53,7 @@ Number of file 0 mappings: 25 - Code(Expression(15, Add)) at (prev + 2, 8) to (start + 0, 15) = ((c6 + c7) + c8) - Code(Counter(9)) at (prev + 0, 16) to (start + 3, 6) -- Code(Expression(12, Sub)) at (prev + 3, 6) to (start + 0, 7) +- Code(Expression(12, Sub)) at (prev + 3, 5) to (start + 0, 6) = (((c6 + c7) + c8) - c9) - Code(Expression(15, Add)) at (prev + 1, 11) to (start + 0, 17) = ((c6 + c7) + c8) @@ -63,7 +63,7 @@ Number of file 0 mappings: 25 - Code(Expression(23, Add)) at (prev + 2, 8) to (start + 0, 15) = ((c10 + c11) + c12) - Code(Counter(13)) at (prev + 0, 16) to (start + 3, 6) -- Code(Expression(20, Sub)) at (prev + 3, 6) to (start + 0, 7) +- Code(Expression(20, Sub)) at (prev + 3, 5) to (start + 0, 6) = (((c10 + c11) + c12) - c13) - Code(Expression(23, Add)) at (prev + 1, 11) to (start + 0, 17) = ((c10 + c11) + c12) diff --git a/tests/coverage/match_or_pattern.coverage b/tests/coverage/match_or_pattern.coverage index 94c7967215c..a65c226e567 100644 --- a/tests/coverage/match_or_pattern.coverage +++ b/tests/coverage/match_or_pattern.coverage @@ -10,7 +10,7 @@ LL| 1| a = 2; LL| 1| b = 0; LL| 1| } - ^0 + ^0 LL| 1| match (a, b) { LL| | // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`. LL| | // This test confirms a fix for Issue #79569. @@ -21,7 +21,7 @@ LL| 1| a = 0; LL| 1| b = 0; LL| 1| } - ^0 + ^0 LL| 1| match (a, b) { LL| 0| (0 | 1, 2 | 3) => {} LL| 1| _ => {} @@ -30,7 +30,7 @@ LL| 1| a = 2; LL| 1| b = 2; LL| 1| } - ^0 + ^0 LL| 1| match (a, b) { LL| 0| (0 | 1, 2 | 3) => {} LL| 1| _ => {} @@ -39,7 +39,7 @@ LL| 1| a = 0; LL| 1| b = 2; LL| 1| } - ^0 + ^0 LL| 1| match (a, b) { LL| 1| (0 | 1, 2 | 3) => {} LL| 0| _ => {} diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map index a3e3b1d09c4..e3f5b49d363 100644 --- a/tests/coverage/mcdc/condition-limit.cov-map +++ b/tests/coverage/mcdc/condition-limit.cov-map @@ -1,5 +1,5 @@ Function name: condition_limit::accept_7_conditions -Raw bytes (232): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 12, 01, 07, 01, 02, 09, 28, 08, 07, 02, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 7a, 1d, 07, 06, 00, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 30, 76, 19, 06, 05, 00, 00, 12, 00, 13, 76, 00, 17, 00, 18, 30, 72, 15, 05, 04, 00, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 30, 6e, 11, 04, 03, 00, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 30, 6a, 0d, 03, 02, 00, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 30, 21, 09, 02, 00, 00, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02] +Raw bytes (232): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 12, 01, 07, 01, 02, 09, 28, 08, 07, 02, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 7a, 1d, 07, 06, 00, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 30, 76, 19, 06, 05, 00, 00, 12, 00, 13, 76, 00, 17, 00, 18, 30, 72, 15, 05, 04, 00, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 30, 6e, 11, 04, 03, 00, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 30, 6a, 0d, 03, 02, 00, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 30, 21, 09, 02, 00, 00, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 05, 00, 06, 97, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 44 @@ -83,7 +83,7 @@ Number of file 0 mappings: 18 true = c8 false = c2 - Code(Counter(8)) at (prev + 0, 40) to (start + 2, 6) -- Code(Expression(38, Add)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(38, Add)) at (prev + 2, 5) to (start + 0, 6) = ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)) - Code(Expression(37, Add)) at (prev + 1, 1) to (start + 0, 2) = (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1))) diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map index 46960d31c01..c0e7d08bb02 100644 --- a/tests/coverage/mcdc/if.cov-map +++ b/tests/coverage/mcdc/if.cov-map @@ -175,7 +175,7 @@ Number of file 0 mappings: 10 Highest counter ID seen: c4 Function name: if::mcdc_nested_if -Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02] +Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 09, 00, 0a, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 13 @@ -215,7 +215,7 @@ Number of file 0 mappings: 14 true = c3 false = c4 - Code(Counter(3)) at (prev + 0, 19) to (start + 2, 10) -- Code(Expression(11, Add)) at (prev + 2, 10) to (start + 0, 11) +- Code(Expression(11, Add)) at (prev + 2, 9) to (start + 0, 10) = (c4 + c5) - Code(Expression(12, Sub)) at (prev + 1, 12) to (start + 2, 6) = ((c0 - c1) - c2) diff --git a/tests/coverage/nested_loops.cov-map b/tests/coverage/nested_loops.cov-map index c145d4c5843..21871ef3206 100644 --- a/tests/coverage/nested_loops.cov-map +++ b/tests/coverage/nested_loops.cov-map @@ -1,5 +1,5 @@ Function name: nested_loops::main -Raw bytes (115): 0x[01, 01, 17, 01, 57, 05, 09, 03, 0d, 4e, 53, 03, 0d, 15, 19, 4b, 09, 4e, 53, 03, 0d, 15, 19, 46, 05, 4b, 09, 4e, 53, 03, 0d, 15, 19, 42, 19, 46, 05, 4b, 09, 4e, 53, 03, 0d, 15, 19, 05, 09, 11, 0d, 0d, 01, 01, 01, 02, 1b, 03, 04, 13, 00, 20, 4e, 01, 0d, 01, 18, 4b, 02, 12, 00, 17, 46, 01, 10, 00, 16, 05, 01, 11, 00, 16, 42, 01, 0e, 03, 16, 3e, 04, 11, 01, 1b, 11, 02, 15, 00, 21, 15, 01, 18, 02, 12, 19, 03, 0e, 00, 0f, 57, 02, 09, 00, 17, 5b, 02, 01, 00, 02] +Raw bytes (115): 0x[01, 01, 17, 01, 57, 05, 09, 03, 0d, 4e, 53, 03, 0d, 15, 19, 4b, 09, 4e, 53, 03, 0d, 15, 19, 46, 05, 4b, 09, 4e, 53, 03, 0d, 15, 19, 42, 19, 46, 05, 4b, 09, 4e, 53, 03, 0d, 15, 19, 05, 09, 11, 0d, 0d, 01, 01, 01, 02, 1b, 03, 04, 13, 00, 20, 4e, 01, 0d, 01, 18, 4b, 02, 12, 00, 17, 46, 01, 10, 00, 16, 05, 01, 11, 00, 16, 42, 01, 0e, 03, 16, 3e, 04, 11, 01, 1b, 11, 02, 15, 00, 21, 15, 01, 18, 02, 12, 19, 03, 0d, 00, 0e, 57, 02, 09, 00, 17, 5b, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 23 @@ -43,7 +43,7 @@ Number of file 0 mappings: 13 = ((((((c0 + (c1 + c2)) - c3) + (c5 + c6)) - c2) - c1) - c6) - Code(Counter(4)) at (prev + 2, 21) to (start + 0, 33) - Code(Counter(5)) at (prev + 1, 24) to (start + 2, 18) -- Code(Counter(6)) at (prev + 3, 14) to (start + 0, 15) +- Code(Counter(6)) at (prev + 3, 13) to (start + 0, 14) - Code(Expression(21, Add)) at (prev + 2, 9) to (start + 0, 23) = (c1 + c2) - Code(Expression(22, Add)) at (prev + 2, 1) to (start + 0, 2) diff --git a/tests/coverage/overflow.cov-map b/tests/coverage/overflow.cov-map index f842ce3e896..f6bfb465bf9 100644 --- a/tests/coverage/overflow.cov-map +++ b/tests/coverage/overflow.cov-map @@ -1,5 +1,5 @@ Function name: overflow::main -Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 10, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] +Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 10, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 09, 00, 0a, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -21,14 +21,14 @@ Number of file 0 mappings: 9 - Code(Expression(4, Sub)) at (prev + 3, 19) to (start + 0, 32) = (((c0 + (c1 + (c2 + c3))) - c4) - c1) - Code(Counter(2)) at (prev + 0, 33) to (start + 3, 10) -- Code(Counter(3)) at (prev + 3, 10) to (start + 0, 11) +- Code(Counter(3)) at (prev + 3, 9) to (start + 0, 10) - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + (c2 + c3)) - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) Highest counter ID seen: c4 Function name: overflow::might_overflow -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 01, 01, 09, 05, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 05, 00, 06, 01, 01, 09, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -36,7 +36,7 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 5, 1) to (start + 1, 18) - Code(Counter(1)) at (prev + 1, 19) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 5, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map index f4a7894cc1c..58a796ff3a2 100644 --- a/tests/coverage/panic_unwind.cov-map +++ b/tests/coverage/panic_unwind.cov-map @@ -1,5 +1,5 @@ Function name: panic_unwind::main -Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] +Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 09, 00, 0a, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -21,7 +21,7 @@ Number of file 0 mappings: 9 - Code(Expression(4, Sub)) at (prev + 2, 19) to (start + 0, 32) = (((c0 + (c1 + (c2 + c3))) - c4) - c1) - Code(Counter(2)) at (prev + 0, 33) to (start + 2, 10) -- Code(Counter(3)) at (prev + 2, 10) to (start + 0, 11) +- Code(Counter(3)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + (c2 + c3)) - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) diff --git a/tests/coverage/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map index b6f1e8f6afe..d1e684efbbc 100644 --- a/tests/coverage/simple_loop.cov-map +++ b/tests/coverage/simple_loop.cov-map @@ -1,5 +1,5 @@ Function name: simple_loop::main -Raw bytes (43): 0x[01, 01, 02, 01, 05, 01, 09, 07, 01, 04, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 07, 05, 0d, 02, 0e, 01, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 01, 06, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 01, 09, 07, 01, 04, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 05, 00, 06, 07, 05, 0d, 02, 0e, 01, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 01, 06, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -8,7 +8,7 @@ Number of expressions: 2 Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 4, 1) to (start + 9, 16) - Code(Counter(1)) at (prev + 10, 5) to (start + 5, 6) -- Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 5, 5) to (start + 0, 6) = (c0 - c1) - Code(Expression(1, Add)) at (prev + 5, 13) to (start + 2, 14) = (c0 + c2) diff --git a/tests/coverage/simple_loop.coverage b/tests/coverage/simple_loop.coverage index b6552c62ff9..237e509f42e 100644 --- a/tests/coverage/simple_loop.coverage +++ b/tests/coverage/simple_loop.coverage @@ -17,7 +17,7 @@ LL| 1| 10 LL| 1| ; LL| 1| } - ^0 + ^0 LL| | LL| | loop LL| | { diff --git a/tests/coverage/simple_match.cov-map b/tests/coverage/simple_match.cov-map index b62edf12650..d8bf9eae4bc 100644 --- a/tests/coverage/simple_match.cov-map +++ b/tests/coverage/simple_match.cov-map @@ -1,5 +1,5 @@ Function name: simple_match::main -Raw bytes (72): 0x[01, 01, 09, 01, 05, 01, 23, 09, 0d, 1f, 11, 01, 23, 09, 0d, 1f, 11, 01, 23, 09, 0d, 0a, 01, 04, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 1f, 05, 09, 00, 0d, 1a, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 1a, 02, 11, 02, 12, 09, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02] +Raw bytes (72): 0x[01, 01, 09, 01, 05, 01, 23, 09, 0d, 1f, 11, 01, 23, 09, 0d, 1f, 11, 01, 23, 09, 0d, 0a, 01, 04, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 05, 00, 06, 1f, 05, 09, 00, 0d, 1a, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 1a, 02, 11, 02, 12, 09, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -15,7 +15,7 @@ Number of expressions: 9 Number of file 0 mappings: 10 - Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Expression(7, Add)) at (prev + 5, 9) to (start + 0, 13) = (c0 + (c2 + c3)) diff --git a/tests/coverage/simple_match.coverage b/tests/coverage/simple_match.coverage index 3a4fc6743f5..e1d5e48a2bf 100644 --- a/tests/coverage/simple_match.coverage +++ b/tests/coverage/simple_match.coverage @@ -11,7 +11,7 @@ LL| 1| if is_true { LL| 1| countdown = 0; LL| 1| } - ^0 + ^0 LL| | LL| | for LL| | _ diff --git a/tests/coverage/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map index 4e7ed059c87..69e13422296 100644 --- a/tests/coverage/sort_groups.cov-map +++ b/tests/coverage/sort_groups.cov-map @@ -1,5 +1,5 @@ Function name: sort_groups::generic_fn::<&str> -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -7,13 +7,13 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) - Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: sort_groups::generic_fn::<()> -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -21,13 +21,13 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) - Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: sort_groups::generic_fn:: -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -35,13 +35,13 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) - Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: sort_groups::generic_fn:: -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -49,13 +49,13 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) - Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: sort_groups::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 06, 00, 07, 01, 01, 05, 02, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -63,7 +63,7 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 6, 1) to (start + 4, 35) - Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 2, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/sort_groups.coverage b/tests/coverage/sort_groups.coverage index 33a4d9546ce..6e8a4eda09f 100644 --- a/tests/coverage/sort_groups.coverage +++ b/tests/coverage/sort_groups.coverage @@ -27,7 +27,7 @@ | LL| 1| if cond { | LL| 1| println!("{}", std::any::type_name::()); | LL| 1| } - | ^0 + | ^0 | LL| 1|} ------------------ | sort_groups::generic_fn::<()>: diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map index ac4e691ea7a..769930110d6 100644 --- a/tests/coverage/unicode.cov-map +++ b/tests/coverage/unicode.cov-map @@ -1,5 +1,5 @@ Function name: unicode::main -Raw bytes (61): 0x[01, 01, 06, 01, 05, 16, 0d, 01, 09, 11, 13, 16, 0d, 01, 09, 09, 01, 0e, 01, 00, 0b, 05, 01, 09, 00, 0c, 03, 00, 10, 00, 1b, 05, 00, 1c, 00, 28, 01, 02, 08, 00, 25, 09, 00, 29, 00, 46, 11, 00, 47, 02, 06, 13, 02, 06, 00, 07, 0f, 02, 05, 01, 02] +Raw bytes (61): 0x[01, 01, 06, 01, 05, 16, 0d, 01, 09, 11, 13, 16, 0d, 01, 09, 09, 01, 0e, 01, 00, 0b, 05, 01, 09, 00, 0c, 03, 00, 10, 00, 1b, 05, 00, 1c, 00, 28, 01, 02, 08, 00, 25, 09, 00, 29, 00, 46, 11, 00, 47, 02, 06, 13, 02, 05, 00, 06, 0f, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 6 @@ -18,7 +18,7 @@ Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 2, 8) to (start + 0, 37) - Code(Counter(2)) at (prev + 0, 41) to (start + 0, 70) - Code(Counter(4)) at (prev + 0, 71) to (start + 2, 6) -- Code(Expression(4, Add)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6) = ((c0 - c2) + c3) - Code(Expression(3, Add)) at (prev + 2, 5) to (start + 1, 2) = (c4 + ((c0 - c2) + c3)) diff --git a/tests/coverage/unicode.coverage b/tests/coverage/unicode.coverage index 305591c7062..84c5f05a8c4 100644 --- a/tests/coverage/unicode.coverage +++ b/tests/coverage/unicode.coverage @@ -18,7 +18,7 @@ LL| 1| if 申し訳ございません() && 申し訳ございません() { ^0 LL| 0| println!("true"); - LL| 1| } + LL| 1| } LL| | LL| 1| サビ(); LL| 1|} diff --git a/tests/coverage/unused.cov-map b/tests/coverage/unused.cov-map index 9f1ad59ce83..e865ac3ee62 100644 --- a/tests/coverage/unused.cov-map +++ b/tests/coverage/unused.cov-map @@ -50,38 +50,38 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: unused::unused_func (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 - Code(Zero) at (prev + 19, 1) to (start + 1, 14) - Code(Zero) at (prev + 1, 15) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: unused::unused_func2 (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 - Code(Zero) at (prev + 25, 1) to (start + 1, 14) - Code(Zero) at (prev + 1, 15) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) Function name: unused::unused_func3 (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 00, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 05, 00, 06, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 - Code(Zero) at (prev + 31, 1) to (start + 1, 14) - Code(Zero) at (prev + 1, 15) to (start + 2, 6) -- Code(Zero) at (prev + 2, 6) to (start + 0, 7) +- Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: (none) diff --git a/tests/coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage index d001eeffd86..d1b0dadda76 100644 --- a/tests/coverage/uses_crate.coverage +++ b/tests/coverage/uses_crate.coverage @@ -14,7 +14,7 @@ $DIR/auxiliary/used_crate.rs: LL| 1| if is_true { LL| 1| countdown = 10; LL| 1| } - ^0 + ^0 LL| 1| use_this_lib_crate(); LL| 1|} LL| | diff --git a/tests/coverage/uses_inline_crate.cov-map b/tests/coverage/uses_inline_crate.cov-map index a6909768162..a482d20e3b4 100644 --- a/tests/coverage/uses_inline_crate.cov-map +++ b/tests/coverage/uses_inline_crate.cov-map @@ -8,7 +8,7 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: used_inline_crate::used_inline_function -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 06, 00, 07, 01, 01, 05, 01, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -16,7 +16,7 @@ Number of expressions: 1 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 20, 1) to (start + 6, 15) - Code(Counter(1)) at (prev + 6, 16) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/uses_inline_crate.coverage b/tests/coverage/uses_inline_crate.coverage index 832a5a6a62b..4671c95aefa 100644 --- a/tests/coverage/uses_inline_crate.coverage +++ b/tests/coverage/uses_inline_crate.coverage @@ -14,7 +14,7 @@ $DIR/auxiliary/used_inline_crate.rs: LL| 1| if is_true { LL| 1| countdown = 10; LL| 1| } - ^0 + ^0 LL| 1| use_this_lib_crate(); LL| 1|} LL| | @@ -28,7 +28,7 @@ $DIR/auxiliary/used_inline_crate.rs: LL| 1| if is_true { LL| 1| countdown = 10; LL| 1| } - ^0 + ^0 LL| 1| use_this_lib_crate(); LL| 1|} LL| | diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index 510aa07f32d..a179824d6c7 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -12,7 +12,7 @@ + coverage Code(Counter(0)) => 10:1 - 10:11; + coverage Code(Expression(0)) => 12:12 - 12:17; + coverage Code(Counter(0)) => 13:13 - 13:18; -+ coverage Code(Counter(1)) => 14:10 - 14:11; ++ coverage Code(Counter(1)) => 14:9 - 14:10; + coverage Code(Counter(0)) => 16:1 - 16:2; + bb0: { diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index 23cdb3d7717..082539369f7 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -11,7 +11,7 @@ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; coverage Code(Counter(0)) => 13:1 - 14:36; coverage Code(Expression(0)) => 14:37 - 14:39; - coverage Code(Counter(1)) => 14:39 - 14:40; + coverage Code(Counter(1)) => 14:38 - 14:39; coverage Code(Counter(0)) => 15:1 - 15:2; coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index f6aa42f3eee..8635818c6a7 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -11,7 +11,7 @@ + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; + coverage Code(Counter(0)) => 13:1 - 14:36; + coverage Code(Expression(0)) => 14:37 - 14:39; -+ coverage Code(Counter(1)) => 14:39 - 14:40; ++ coverage Code(Counter(1)) => 14:38 - 14:39; + coverage Code(Counter(0)) => 15:1 - 15:2; + coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; + -- cgit 1.4.1-3-g733a5 From 2a9cc8f4d6aee54ecf1882bfaa690165b52d66f2 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 11 Nov 2024 15:32:25 +0000 Subject: Declare all MIR passes in a list --- compiler/rustc_mir_transform/src/lib.rs | 204 ++++++++++++++++------- compiler/rustc_mir_transform/src/pass_manager.rs | 12 +- 2 files changed, 154 insertions(+), 62 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index e18f66ac0a3..66ac3d30ca4 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -40,77 +40,159 @@ use tracing::{debug, trace}; #[macro_use] mod pass_manager; +use std::sync::LazyLock; + use pass_manager::{self as pm, Lint, MirLint, MirPass, WithMinOptLevel}; -mod abort_unwinding_calls; -mod add_call_guards; -mod add_moves_for_packed_drops; -mod add_retag; -mod add_subtyping_projections; -mod check_alignment; -mod check_const_item_mutation; -mod check_packed_ref; -mod check_undefined_transmutes; -// This pass is public to allow external drivers to perform MIR cleanup -pub mod cleanup_post_borrowck; -mod copy_prop; -mod coroutine; mod cost_checker; -mod coverage; mod cross_crate_inline; -mod ctfe_limit; -mod dataflow_const_prop; -mod dead_store_elimination; mod deduce_param_attrs; -mod deduplicate_blocks; -mod deref_separator; -mod dest_prop; -pub mod dump_mir; -mod early_otherwise_branch; -mod elaborate_box_derefs; -mod elaborate_drops; mod errors; mod ffi_unwind_calls; -mod function_item_references; -mod gvn; -// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden -// by custom rustc drivers, running all the steps by themselves. See #114628. -pub mod inline; -mod instsimplify; -mod jump_threading; -mod known_panics_lint; -mod large_enums; mod lint; -mod lower_intrinsics; -mod lower_slice_len; -mod match_branches; -mod mentioned_items; -mod multiple_return_terminators; -mod nrvo; -mod post_drop_elaboration; -mod prettify; -mod promote_consts; -mod ref_prop; -mod remove_noop_landing_pads; -mod remove_place_mention; -mod remove_storage_markers; -mod remove_uninit_drops; -mod remove_unneeded_drops; -mod remove_zsts; -mod required_consts; -mod reveal_all; -mod sanity_check; mod shim; mod ssa; -// This pass is public to allow external drivers to perform MIR cleanup -pub mod simplify; -mod simplify_branches; -mod simplify_comparison_integral; -mod single_use_consts; -mod sroa; -mod unreachable_enum_branching; -mod unreachable_prop; -mod validate; + +/// We import passes via this macro so that we can have a static list of pass names +/// (used to verify CLI arguments). It takes a list of modules, followed by the passes +/// declared within them. +/// ```ignore,macro-test +/// declare_passes! { +/// // Declare a single pass from the module `abort_unwinding_calls` +/// mod abort_unwinding_calls : AbortUnwindingCalls; +/// // When passes are grouped together as an enum, declare the two constituent passes +/// mod add_call_guards : AddCallGuards { +/// AllCallEdges, +/// CriticalCallEdges +/// }; +/// // Declares multiple pass groups, each containing their own constituent passes +/// mod simplify : SimplifyCfg { +/// Initial, +/// /* omitted */ +/// }, SimplifyLocals { +/// BeforeConstProp, +/// /* omitted */ +/// }; +/// } +/// ``` +macro_rules! declare_passes { + ( + $( + $vis:vis mod $mod_name:ident : $($pass_name:ident $( { $($ident:ident),* } )?),+ $(,)?; + )* + ) => { + $( + $vis mod $mod_name; + $( + // Make sure the type name is correct + #[allow(unused_imports)] + use $mod_name::$pass_name as _; + )+ + )* + + #[cfg(debug_assertions)] + static PASS_NAMES: LazyLock> = LazyLock::new(|| vec![ + // Fake marker pass + "PreCodegen".to_string(), + $( + $( + stringify!($pass_name).to_string(), + $( + $( + $mod_name::$pass_name::$ident.name().to_string(), + )* + )? + )+ + )* + ]); + }; +} + +declare_passes! { + mod abort_unwinding_calls : AbortUnwindingCalls; + mod add_call_guards : AddCallGuards { AllCallEdges, CriticalCallEdges }; + mod add_moves_for_packed_drops : AddMovesForPackedDrops; + mod add_retag : AddRetag; + mod add_subtyping_projections : Subtyper; + mod check_alignment : CheckAlignment; + mod check_const_item_mutation : CheckConstItemMutation; + mod check_packed_ref : CheckPackedRef; + mod check_undefined_transmutes : CheckUndefinedTransmutes; + // This pass is public to allow external drivers to perform MIR cleanup + pub mod cleanup_post_borrowck : CleanupPostBorrowck; + + mod copy_prop : CopyProp; + mod coroutine : StateTransform; + mod coverage : InstrumentCoverage; + mod ctfe_limit : CtfeLimit; + mod dataflow_const_prop : DataflowConstProp; + mod dead_store_elimination : DeadStoreElimination { + Initial, + Final + }; + mod deduplicate_blocks : DeduplicateBlocks; + mod deref_separator : Derefer; + mod dest_prop : DestinationPropagation; + pub mod dump_mir : Marker; + mod early_otherwise_branch : EarlyOtherwiseBranch; + mod elaborate_box_derefs : ElaborateBoxDerefs; + mod elaborate_drops : ElaborateDrops; + mod function_item_references : FunctionItemReferences; + mod gvn : GVN; + // Made public so that `mir_drops_elaborated_and_const_checked` can be overridden + // by custom rustc drivers, running all the steps by themselves. See #114628. + pub mod inline : Inline; + mod instsimplify : InstSimplify { BeforeInline, AfterSimplifyCfg }; + mod jump_threading : JumpThreading; + mod known_panics_lint : KnownPanicsLint; + mod large_enums : EnumSizeOpt; + mod lower_intrinsics : LowerIntrinsics; + mod lower_slice_len : LowerSliceLenCalls; + mod match_branches : MatchBranchSimplification; + mod mentioned_items : MentionedItems; + mod multiple_return_terminators : MultipleReturnTerminators; + mod nrvo : RenameReturnPlace; + mod post_drop_elaboration : CheckLiveDrops; + mod prettify : ReorderBasicBlocks, ReorderLocals; + mod promote_consts : PromoteTemps; + mod ref_prop : ReferencePropagation; + mod remove_noop_landing_pads : RemoveNoopLandingPads; + mod remove_place_mention : RemovePlaceMention; + mod remove_storage_markers : RemoveStorageMarkers; + mod remove_uninit_drops : RemoveUninitDrops; + mod remove_unneeded_drops : RemoveUnneededDrops; + mod remove_zsts : RemoveZsts; + mod required_consts : RequiredConstsVisitor; + mod reveal_all : RevealAll; + mod sanity_check : SanityCheck; + // This pass is public to allow external drivers to perform MIR cleanup + pub mod simplify : + SimplifyCfg { + Initial, + PromoteConsts, + RemoveFalseEdges, + PostAnalysis, + PreOptimizations, + Final, + MakeShim, + AfterUnreachableEnumBranching + }, + SimplifyLocals { + BeforeConstProp, + AfterGVN, + Final + }; + mod simplify_branches : SimplifyConstCondition { + AfterConstProp, + Final + }; + mod simplify_comparison_integral : SimplifyComparisonIntegral; + mod single_use_consts : SingleUseConsts; + mod sroa : ScalarReplacementOfAggregates; + mod unreachable_enum_branching : UnreachableEnumBranching; + mod unreachable_prop : UnreachablePropagation; + mod validate : Validator; +} rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 29f8b4f6e4d..37c9f5b4c21 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -1,7 +1,7 @@ use std::cell::RefCell; use std::collections::hash_map::Entry; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_middle::mir::{self, Body, MirPhase, RuntimePhase}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -198,6 +198,16 @@ fn run_passes_inner<'tcx>( let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); + #[cfg(debug_assertions)] + { + let used_passes: FxIndexSet<_> = passes.iter().map(|p| p.name()).collect(); + let known_passes: FxIndexSet<_> = crate::PASS_NAMES.iter().map(|p| p.as_str()).collect(); + + for &name in used_passes.difference(&known_passes) { + tcx.dcx().bug(format!("pass `{name}` is not declared in `PASS_NAMES`")); + } + } + let prof_arg = tcx.sess.prof.enabled().then(|| format!("{:?}", body.source.def_id())); if !body.should_skip() { -- cgit 1.4.1-3-g733a5 From 94371d5a8cf3c0480a744e4727837e9d7b2281b0 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 11 Nov 2024 16:36:00 +0000 Subject: Validate and test `-Zmir-enable-passes` --- compiler/rustc_mir_transform/messages.ftl | 2 ++ compiler/rustc_mir_transform/src/errors.rs | 6 ++++++ compiler/rustc_mir_transform/src/lib.rs | 1 - compiler/rustc_mir_transform/src/pass_manager.rs | 24 ++++++++++++++++++---- .../enable_passes_validation.all_unknown.stderr | 14 +++++++++++++ tests/ui/mir/enable_passes_validation.empty.stderr | 2 ++ tests/ui/mir/enable_passes_validation.mixed.stderr | 8 ++++++++ tests/ui/mir/enable_passes_validation.rs | 21 +++++++++++++++++++ .../mir/enable_passes_validation.unprefixed.stderr | 2 ++ 9 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 tests/ui/mir/enable_passes_validation.all_unknown.stderr create mode 100644 tests/ui/mir/enable_passes_validation.empty.stderr create mode 100644 tests/ui/mir/enable_passes_validation.mixed.stderr create mode 100644 tests/ui/mir/enable_passes_validation.rs create mode 100644 tests/ui/mir/enable_passes_validation.unprefixed.stderr (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index c8992b8b834..9bbfae17fd9 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -34,3 +34,5 @@ mir_transform_undefined_transmute = pointers cannot be transmuted to integers du .note = at compile-time, pointers do not have an integer value .note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior .help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html + +mir_transform_unknown_pass_name = MIR pass `{$name}` is unknown and will be ignored diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 8b309147c64..2d9eeddea2e 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -38,6 +38,12 @@ pub(crate) struct UnalignedPackedRef { pub span: Span, } +#[derive(Diagnostic)] +#[diag(mir_transform_unknown_pass_name)] +pub(crate) struct UnknownPassName<'a> { + pub(crate) name: &'a str, +} + pub(crate) struct AssertLint

{ pub span: Span, pub assert_kind: AssertKind

, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 66ac3d30ca4..68904c65252 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -90,7 +90,6 @@ macro_rules! declare_passes { )+ )* - #[cfg(debug_assertions)] static PASS_NAMES: LazyLock> = LazyLock::new(|| vec![ // Fake marker pass "PreCodegen".to_string(), diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 37c9f5b4c21..bc960ae0f56 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -8,7 +8,7 @@ use rustc_session::Session; use tracing::trace; use crate::lint::lint_body; -use crate::validate; +use crate::{errors, validate}; thread_local! { static PASS_NAMES: RefCell> = { @@ -198,13 +198,29 @@ fn run_passes_inner<'tcx>( let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); + let named_passes: FxIndexSet<_> = + overridden_passes.iter().map(|(name, _)| name.as_str()).collect(); + let known_passes: FxIndexSet<_> = crate::PASS_NAMES.iter().map(|p| p.as_str()).collect(); + + for &name in named_passes.difference(&known_passes) { + tcx.dcx().emit_warn(errors::UnknownPassName { name }); + } + + // Verify that no passes are missing from the `declare_passes` invocation #[cfg(debug_assertions)] + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] { let used_passes: FxIndexSet<_> = passes.iter().map(|p| p.name()).collect(); - let known_passes: FxIndexSet<_> = crate::PASS_NAMES.iter().map(|p| p.as_str()).collect(); - for &name in used_passes.difference(&known_passes) { - tcx.dcx().bug(format!("pass `{name}` is not declared in `PASS_NAMES`")); + let undeclared = used_passes.difference(&known_passes).collect::>(); + if let Some((name, rest)) = undeclared.split_first() { + let mut err = + tcx.dcx().struct_bug(format!("pass `{name}` is not declared in `PASS_NAMES`")); + for name in rest { + err.note(format!("pass `{name}` is also not declared in `PASS_NAMES`")); + } + err.emit(); } } diff --git a/tests/ui/mir/enable_passes_validation.all_unknown.stderr b/tests/ui/mir/enable_passes_validation.all_unknown.stderr new file mode 100644 index 00000000000..85a942c00ed --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.all_unknown.stderr @@ -0,0 +1,14 @@ +warning: MIR pass `ThisPass` is unknown and will be ignored + +warning: MIR pass `DoesNotExist` is unknown and will be ignored + +warning: MIR pass `ThisPass` is unknown and will be ignored + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: MIR pass `DoesNotExist` is unknown and will be ignored + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 4 warnings emitted + diff --git a/tests/ui/mir/enable_passes_validation.empty.stderr b/tests/ui/mir/enable_passes_validation.empty.stderr new file mode 100644 index 00000000000..0e922663acc --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.empty.stderr @@ -0,0 +1,2 @@ +error: incorrect value `` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected + diff --git a/tests/ui/mir/enable_passes_validation.mixed.stderr b/tests/ui/mir/enable_passes_validation.mixed.stderr new file mode 100644 index 00000000000..5aace86abc0 --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.mixed.stderr @@ -0,0 +1,8 @@ +warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored + +warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 2 warnings emitted + diff --git a/tests/ui/mir/enable_passes_validation.rs b/tests/ui/mir/enable_passes_validation.rs new file mode 100644 index 00000000000..957e7d4d96d --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.rs @@ -0,0 +1,21 @@ +//@ revisions: empty unprefixed all_unknown all_known mixed + +//@[empty] compile-flags: -Zmir-enable-passes= +//@[empty] error-pattern error: incorrect value `` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected + +//@[unprefixed] compile-flags: -Zmir-enable-passes=CheckAlignment +//@[unprefixed] error-pattern error: incorrect value `CheckAlignment` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected + +//@[all_unknown] check-pass +//@[all_unknown] compile-flags: -Zmir-enable-passes=+ThisPass,-DoesNotExist +//@[all_unknown] error-pattern: warning: MIR pass `ThisPass` is unknown and will be ignored +//@[all_unknown] error-pattern: warning: MIR pass `DoesNotExist` is unknown and will be ignored + +//@[all_known] check-pass +//@[all_known] compile-flags: -Zmir-enable-passes=+CheckAlignment,+LowerIntrinsics + +//@[mixed] check-pass +//@[mixed] compile-flags: -Zmir-enable-passes=+ThisPassDoesNotExist,+CheckAlignment +//@[mixed] error-pattern: warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored + +fn main() {} diff --git a/tests/ui/mir/enable_passes_validation.unprefixed.stderr b/tests/ui/mir/enable_passes_validation.unprefixed.stderr new file mode 100644 index 00000000000..697589448f4 --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.unprefixed.stderr @@ -0,0 +1,2 @@ +error: incorrect value `CheckAlignment` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected + -- cgit 1.4.1-3-g733a5 From 12036830d039134c447a1d7299a59560cd4a39d0 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 11 Nov 2024 16:43:49 +0000 Subject: Store known passes as an IndexSet --- compiler/rustc_mir_transform/src/lib.rs | 10 +++++----- compiler/rustc_mir_transform/src/pass_manager.rs | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 68904c65252..d2d5facbbdc 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -90,20 +90,20 @@ macro_rules! declare_passes { )+ )* - static PASS_NAMES: LazyLock> = LazyLock::new(|| vec![ + static PASS_NAMES: LazyLock> = LazyLock::new(|| [ // Fake marker pass - "PreCodegen".to_string(), + "PreCodegen", $( $( - stringify!($pass_name).to_string(), + stringify!($pass_name), $( $( - $mod_name::$pass_name::$ident.name().to_string(), + $mod_name::$pass_name::$ident.name(), )* )? )+ )* - ]); + ].into_iter().collect()); }; } diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index bc960ae0f56..e26e0c78b29 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -200,9 +200,8 @@ fn run_passes_inner<'tcx>( let named_passes: FxIndexSet<_> = overridden_passes.iter().map(|(name, _)| name.as_str()).collect(); - let known_passes: FxIndexSet<_> = crate::PASS_NAMES.iter().map(|p| p.as_str()).collect(); - for &name in named_passes.difference(&known_passes) { + for &name in named_passes.difference(&*crate::PASS_NAMES) { tcx.dcx().emit_warn(errors::UnknownPassName { name }); } @@ -213,7 +212,7 @@ fn run_passes_inner<'tcx>( { let used_passes: FxIndexSet<_> = passes.iter().map(|p| p.name()).collect(); - let undeclared = used_passes.difference(&known_passes).collect::>(); + let undeclared = used_passes.difference(&*crate::PASS_NAMES).collect::>(); if let Some((name, rest)) = undeclared.split_first() { let mut err = tcx.dcx().struct_bug(format!("pass `{name}` is not declared in `PASS_NAMES`")); -- cgit 1.4.1-3-g733a5 From 8c64e9d17dad7d6e8a9f00191d8f55bd14b44aef Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 11 Nov 2024 16:51:39 +0000 Subject: Rename `PASS_NAMES` to disambiguate --- compiler/rustc_mir_transform/src/pass_manager.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index e26e0c78b29..779e7f22101 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -11,14 +11,15 @@ use crate::lint::lint_body; use crate::{errors, validate}; thread_local! { - static PASS_NAMES: RefCell> = { + /// Maps MIR pass names to a snake case form to match profiling naming style + static PASS_TO_PROFILER_NAMES: RefCell> = { RefCell::new(FxHashMap::default()) }; } /// Converts a MIR pass name into a snake case form to match the profiling naming style. fn to_profiler_name(type_name: &'static str) -> &'static str { - PASS_NAMES.with(|names| match names.borrow_mut().entry(type_name) { + PASS_TO_PROFILER_NAMES.with(|names| match names.borrow_mut().entry(type_name) { Entry::Occupied(e) => *e.get(), Entry::Vacant(e) => { let snake_case: String = type_name -- cgit 1.4.1-3-g733a5 From 5d818914af2760972943db448d2a08de27900c96 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 14 Nov 2024 14:17:20 -0600 Subject: Always inline functions signatures containing `f16` or `f128` There are a handful of tier 2 and tier 3 targets that cause a LLVM crash or linker error when generating code that contains `f16` or `f128`. The cranelift backend also does not support these types. To work around this, every function in `std` or `core` that contains these types must be marked `#[inline]` in order to avoid sending any code to the backend unless specifically requested. However, this is inconvenient and easy to forget. Introduce a check for these types in the frontend that automatically inlines any function signatures that take or return `f16` or `f128`. Note that this is not a perfect fix because it does not account for the types being passed by reference or as members of aggregate types, but this is sufficient for what is currently needed in the standard library. Fixes: https://github.com/rust-lang/rust/issues/133035 Closes: https://github.com/rust-lang/rust/pull/133037 --- .../rustc_mir_transform/src/cross_crate_inline.rs | 10 ++++++++ tests/codegen/float/f16-f128-inline.rs | 29 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/codegen/float/f16-f128-inline.rs (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 42cbece32d8..589be81558c 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -50,6 +50,16 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { _ => {} } + let sig = tcx.fn_sig(def_id).instantiate_identity(); + for ty in sig.inputs().skip_binder().iter().chain(std::iter::once(&sig.output().skip_binder())) + { + // FIXME(f16_f128): in order to avoid crashes building `core`, always inline to skip + // codegen if the function is not used. + if ty == &tcx.types.f16 || ty == &tcx.types.f128 { + return true; + } + } + // Don't do any inference when incremental compilation is enabled; the additional inlining that // inference permits also creates more work for small edits. if tcx.sess.opts.incremental.is_some() { diff --git a/tests/codegen/float/f16-f128-inline.rs b/tests/codegen/float/f16-f128-inline.rs new file mode 100644 index 00000000000..aa2c38c209e --- /dev/null +++ b/tests/codegen/float/f16-f128-inline.rs @@ -0,0 +1,29 @@ +//@ revisions: default nopt +//@[nopt] compile-flags: -Copt-level=0 -Zcross-crate-inline-threshold=never -Zmir-opt-level=0 -Cno-prepopulate-passes + +// Ensure that functions using `f16` and `f128` are always inlined to avoid crashes +// when the backend does not support these types. + +#![crate_type = "lib"] +#![feature(f128)] +#![feature(f16)] + +pub fn f16_arg(_a: f16) { + // CHECK-NOT: f16_arg + todo!() +} + +pub fn f16_ret() -> f16 { + // CHECK-NOT: f16_ret + todo!() +} + +pub fn f128_arg(_a: f128) { + // CHECK-NOT: f128_arg + todo!() +} + +pub fn f128_ret() -> f128 { + // CHECK-NOT: f128_ret + todo!() +} -- cgit 1.4.1-3-g733a5 From 9cba14b95bb07a5b31ed1aac2bf4eadd248232da Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 15 Nov 2024 13:53:31 +0100 Subject: use `TypingEnv` when no `infcx` is available the behavior of the type system not only depends on the current assumptions, but also the currentnphase of the compiler. This is mostly necessary as we need to decide whether and how to reveal opaque types. We track this via the `TypingMode`. --- .../src/diagnostics/conflict_errors.rs | 19 +++- compiler/rustc_borrowck/src/diagnostics/mod.rs | 2 +- .../src/diagnostics/region_errors.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- compiler/rustc_codegen_cranelift/src/abi/mod.rs | 2 +- compiler/rustc_codegen_cranelift/src/base.rs | 10 +- compiler/rustc_codegen_cranelift/src/common.rs | 18 ++-- compiler/rustc_codegen_cranelift/src/constant.rs | 11 +- .../rustc_codegen_cranelift/src/debuginfo/mod.rs | 8 +- compiler/rustc_codegen_cranelift/src/inline_asm.rs | 10 +- .../rustc_codegen_cranelift/src/intrinsics/mod.rs | 9 +- compiler/rustc_codegen_cranelift/src/lib.rs | 2 +- compiler/rustc_codegen_cranelift/src/main_shim.rs | 6 +- compiler/rustc_codegen_cranelift/src/unsize.rs | 3 +- .../rustc_codegen_cranelift/src/value_and_place.rs | 18 ++-- compiler/rustc_codegen_gcc/src/builder.rs | 10 +- compiler/rustc_codegen_gcc/src/consts.rs | 2 +- compiler/rustc_codegen_gcc/src/context.rs | 16 +-- compiler/rustc_codegen_gcc/src/int.rs | 7 +- compiler/rustc_codegen_gcc/src/intrinsic/mod.rs | 6 +- compiler/rustc_codegen_gcc/src/intrinsic/simd.rs | 10 +- compiler/rustc_codegen_gcc/src/mono_item.rs | 9 +- compiler/rustc_codegen_llvm/src/builder.rs | 10 +- compiler/rustc_codegen_llvm/src/callee.rs | 9 +- compiler/rustc_codegen_llvm/src/consts.rs | 6 +- compiler/rustc_codegen_llvm/src/context.rs | 10 +- .../src/debuginfo/create_scope_map.rs | 4 +- .../rustc_codegen_llvm/src/debuginfo/metadata.rs | 19 ++-- .../src/debuginfo/metadata/type_map.rs | 26 +++-- compiler/rustc_codegen_llvm/src/debuginfo/mod.rs | 11 +- compiler/rustc_codegen_llvm/src/debuginfo/utils.rs | 4 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 13 ++- compiler/rustc_codegen_llvm/src/mono_item.rs | 9 +- .../rustc_codegen_ssa/src/back/symbol_export.rs | 6 +- compiler/rustc_codegen_ssa/src/base.rs | 13 ++- .../rustc_codegen_ssa/src/debuginfo/type_names.rs | 31 +++--- compiler/rustc_codegen_ssa/src/mir/block.rs | 14 +-- compiler/rustc_codegen_ssa/src/mir/constant.rs | 6 +- compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 6 +- compiler/rustc_codegen_ssa/src/traits/type_.rs | 16 +-- .../rustc_const_eval/src/check_consts/check.rs | 11 +- compiler/rustc_const_eval/src/check_consts/mod.rs | 8 +- compiler/rustc_const_eval/src/check_consts/ops.rs | 8 +- .../src/check_consts/post_drop_elaboration.rs | 8 +- .../rustc_const_eval/src/check_consts/qualifs.rs | 24 +++-- .../rustc_const_eval/src/check_consts/resolver.rs | 5 +- .../src/const_eval/eval_queries.rs | 6 +- .../rustc_const_eval/src/const_eval/machine.rs | 3 +- .../rustc_const_eval/src/const_eval/valtrees.rs | 11 +- compiler/rustc_const_eval/src/interpret/call.rs | 58 +++++------ compiler/rustc_const_eval/src/interpret/cast.rs | 4 +- .../rustc_const_eval/src/interpret/eval_context.rs | 52 ++++------ .../rustc_const_eval/src/interpret/intrinsics.rs | 9 +- compiler/rustc_const_eval/src/interpret/memory.rs | 2 +- compiler/rustc_const_eval/src/interpret/operand.rs | 21 ++-- .../rustc_const_eval/src/interpret/operator.rs | 2 +- compiler/rustc_const_eval/src/interpret/place.rs | 12 +-- compiler/rustc_const_eval/src/interpret/stack.rs | 15 ++- compiler/rustc_const_eval/src/interpret/step.rs | 3 +- .../rustc_const_eval/src/interpret/validity.rs | 6 +- compiler/rustc_const_eval/src/lib.rs | 2 +- compiler/rustc_const_eval/src/util/alignment.rs | 6 +- .../src/util/check_validity_requirement.rs | 10 +- .../rustc_const_eval/src/util/compare_types.rs | 13 +-- compiler/rustc_hir_analysis/src/check/check.rs | 22 ++-- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 5 +- .../rustc_hir_analysis/src/coherence/builtin.rs | 4 +- .../rustc_hir_analysis/src/hir_ty_lowering/cmse.rs | 10 +- compiler/rustc_hir_typeck/src/expr.rs | 6 +- compiler/rustc_hir_typeck/src/intrinsicck.rs | 4 +- compiler/rustc_hir_typeck/src/upvar.rs | 15 ++- compiler/rustc_hir_typeck/src/writeback.rs | 4 +- compiler/rustc_infer/src/infer/mod.rs | 46 ++++++++- compiler/rustc_lint/src/builtin.rs | 6 +- compiler/rustc_lint/src/context.rs | 14 ++- .../rustc_lint/src/for_loops_over_fallibles.rs | 4 +- compiler/rustc_lint/src/foreign_modules.rs | 30 +++--- compiler/rustc_lint/src/if_let_rescope.rs | 2 +- compiler/rustc_lint/src/internal.rs | 5 +- compiler/rustc_lint/src/let_underscore.rs | 2 +- compiler/rustc_lint/src/non_fmt_panic.rs | 16 +-- compiler/rustc_lint/src/noop_method_call.rs | 4 +- compiler/rustc_lint/src/tail_expr_drop_order.rs | 11 +- compiler/rustc_lint/src/types.rs | 45 ++++---- compiler/rustc_lint/src/unused.rs | 4 +- compiler/rustc_metadata/src/native_libs.rs | 4 +- compiler/rustc_middle/src/mir/consts.rs | 61 ++++++----- compiler/rustc_middle/src/mir/interpret/mod.rs | 8 +- compiler/rustc_middle/src/mir/interpret/queries.rs | 17 ++- compiler/rustc_middle/src/mir/mod.rs | 27 +++-- compiler/rustc_middle/src/mir/statement.rs | 4 +- compiler/rustc_middle/src/mir/syntax.rs | 9 +- compiler/rustc_middle/src/query/keys.rs | 14 ++- compiler/rustc_middle/src/query/mod.rs | 26 ++--- compiler/rustc_middle/src/thir.rs | 29 +++--- compiler/rustc_middle/src/ty/adt.rs | 5 +- compiler/rustc_middle/src/ty/consts.rs | 27 +++-- compiler/rustc_middle/src/ty/context.rs | 12 ++- .../src/ty/inhabitedness/inhabited_predicate.rs | 37 ++++--- compiler/rustc_middle/src/ty/inhabitedness/mod.rs | 8 +- compiler/rustc_middle/src/ty/instance.rs | 41 ++++---- compiler/rustc_middle/src/ty/layout.rs | 115 +++++++++++---------- compiler/rustc_middle/src/ty/mod.rs | 100 +++++++++++++++++- .../src/ty/normalize_erasing_regions.rs | 49 +++++---- compiler/rustc_middle/src/ty/util.rs | 58 ++++++----- compiler/rustc_middle/src/ty/vtable.rs | 4 +- compiler/rustc_middle/src/util/call_kind.rs | 8 +- compiler/rustc_mir_build/src/build/custom/mod.rs | 6 +- .../src/build/custom/parse/instruction.rs | 4 +- .../rustc_mir_build/src/build/expr/as_constant.rs | 3 +- .../rustc_mir_build/src/build/expr/as_operand.rs | 2 +- .../rustc_mir_build/src/build/expr/as_rvalue.rs | 18 ++-- compiler/rustc_mir_build/src/build/expr/into.rs | 6 +- compiler/rustc_mir_build/src/build/expr/stmt.rs | 2 +- .../src/build/matches/match_pair.rs | 2 +- compiler/rustc_mir_build/src/build/matches/test.rs | 17 +-- compiler/rustc_mir_build/src/build/misc.rs | 2 +- compiler/rustc_mir_build/src/build/mod.rs | 4 + compiler/rustc_mir_build/src/build/scope.rs | 2 +- compiler/rustc_mir_build/src/check_unsafety.rs | 4 +- compiler/rustc_mir_build/src/errors.rs | 2 +- compiler/rustc_mir_build/src/lints.rs | 13 ++- compiler/rustc_mir_build/src/thir/constant.rs | 5 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 7 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 12 +++ .../src/thir/pattern/check_match.rs | 6 +- .../src/thir/pattern/const_to_pat.rs | 15 ++- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 2 +- compiler/rustc_mir_dataflow/src/elaborate_drops.rs | 13 ++- compiler/rustc_mir_dataflow/src/value_analysis.rs | 16 +-- .../src/add_moves_for_packed_drops.rs | 10 +- .../rustc_mir_transform/src/check_packed_ref.rs | 9 +- compiler/rustc_mir_transform/src/coroutine.rs | 12 +-- compiler/rustc_mir_transform/src/cost_checker.rs | 10 +- .../rustc_mir_transform/src/dataflow_const_prop.rs | 43 ++++---- .../rustc_mir_transform/src/deduce_param_attrs.rs | 6 +- .../rustc_mir_transform/src/elaborate_drops.rs | 22 ++-- compiler/rustc_mir_transform/src/gvn.rs | 13 ++- compiler/rustc_mir_transform/src/inline.rs | 55 ++++------ compiler/rustc_mir_transform/src/inline/cycle.rs | 15 ++- compiler/rustc_mir_transform/src/instsimplify.rs | 12 ++- compiler/rustc_mir_transform/src/jump_threading.rs | 14 +-- .../rustc_mir_transform/src/known_panics_lint.rs | 31 +++--- compiler/rustc_mir_transform/src/large_enums.rs | 11 +- compiler/rustc_mir_transform/src/lib.rs | 18 ++-- compiler/rustc_mir_transform/src/match_branches.rs | 56 +++++----- compiler/rustc_mir_transform/src/promote_consts.rs | 6 +- .../rustc_mir_transform/src/remove_uninit_drops.rs | 22 ++-- .../src/remove_unneeded_drops.rs | 10 +- compiler/rustc_mir_transform/src/remove_zsts.rs | 8 +- compiler/rustc_mir_transform/src/reveal_all.rs | 12 ++- compiler/rustc_mir_transform/src/shim.rs | 14 +-- .../src/shim/async_destructor_ctor.rs | 8 +- .../rustc_mir_transform/src/simplify_branches.rs | 8 +- .../src/simplify_comparison_integral.rs | 4 +- compiler/rustc_mir_transform/src/sroa.rs | 14 +-- .../src/unreachable_enum_branching.rs | 4 +- compiler/rustc_mir_transform/src/validate.rs | 54 +++++----- compiler/rustc_monomorphize/src/collector.rs | 49 ++++++--- compiler/rustc_monomorphize/src/lib.rs | 4 +- .../src/mono_checks/abi_check.rs | 17 +-- .../src/mono_checks/move_check.rs | 6 +- compiler/rustc_monomorphize/src/partitioning.rs | 2 +- compiler/rustc_monomorphize/src/util.rs | 10 +- .../src/solve/trait_goals.rs | 6 +- compiler/rustc_passes/src/abi_test.rs | 36 ++++--- compiler/rustc_passes/src/dead.rs | 11 +- compiler/rustc_passes/src/layout_test.rs | 37 +++---- compiler/rustc_passes/src/liveness.rs | 2 +- compiler/rustc_pattern_analysis/src/rustc.rs | 36 ++++--- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 4 +- .../src/cfi/typeid/itanium_cxx_abi/mod.rs | 4 +- .../src/cfi/typeid/itanium_cxx_abi/transform.rs | 18 ++-- compiler/rustc_smir/src/rustc_smir/alloc.rs | 8 +- compiler/rustc_smir/src/rustc_smir/builder.rs | 4 +- compiler/rustc_smir/src/rustc_smir/context.rs | 48 ++++++--- compiler/rustc_symbol_mangling/src/v0.rs | 9 +- .../infer/nice_region_error/static_impl_trait.rs | 2 +- .../error_reporting/traits/fulfillment_errors.rs | 2 +- .../src/traits/dyn_compatibility.rs | 6 +- compiler/rustc_trait_selection/src/traits/mod.rs | 5 +- .../src/traits/query/dropck_outlives.rs | 23 +++-- .../src/traits/select/candidate_assembly.rs | 14 ++- .../rustc_trait_selection/src/traits/vtable.rs | 8 +- compiler/rustc_traits/src/codegen.rs | 9 +- compiler/rustc_traits/src/dropck_outlives.rs | 6 +- .../rustc_traits/src/normalize_erasing_regions.rs | 8 +- .../rustc_transmute/src/maybe_transmutable/mod.rs | 4 +- compiler/rustc_ty_utils/src/abi.rs | 38 +++---- compiler/rustc_ty_utils/src/instance.rs | 30 +++--- compiler/rustc_ty_utils/src/layout.rs | 44 ++++---- compiler/rustc_ty_utils/src/layout/invariant.rs | 2 +- compiler/rustc_ty_utils/src/needs_drop.rs | 46 +++++---- compiler/rustc_type_ir/src/infer_ctxt.rs | 2 + compiler/rustc_type_ir/src/interner.rs | 9 +- src/librustdoc/clean/mod.rs | 6 +- src/librustdoc/clean/types.rs | 6 +- src/librustdoc/clean/utils.rs | 5 +- src/librustdoc/core.rs | 9 +- src/librustdoc/html/render/type_layout.rs | 6 +- .../clippy/clippy_lints/src/assigning_clones.rs | 2 +- .../clippy_lints/src/bool_assert_comparison.rs | 2 +- src/tools/clippy/clippy_lints/src/dereference.rs | 9 +- .../clippy/clippy_lints/src/drop_forget_ref.rs | 4 +- .../src/iter_not_returning_iterator.rs | 2 +- .../clippy_lints/src/iter_without_into_iter.rs | 2 +- .../clippy/clippy_lints/src/large_const_arrays.rs | 4 +- src/tools/clippy/clippy_lints/src/large_futures.rs | 2 +- .../clippy/clippy_lints/src/large_stack_frames.rs | 4 +- .../clippy_lints/src/loops/explicit_iter_loop.rs | 12 +-- .../clippy_lints/src/methods/needless_collect.rs | 6 +- .../src/methods/unnecessary_min_or_max.rs | 2 +- .../src/methods/unnecessary_to_owned.rs | 2 +- .../clippy/clippy_lints/src/methods/zst_offset.rs | 2 +- .../src/needless_borrows_for_generic_args.rs | 2 +- .../clippy/clippy_lints/src/non_copy_const.rs | 18 ++-- .../src/operators/const_comparisons.rs | 2 +- .../clippy_lints/src/operators/erasing_op.rs | 2 +- .../clippy/clippy_lints/src/operators/float_cmp.rs | 3 +- .../clippy/clippy_lints/src/redundant_slicing.rs | 2 +- src/tools/clippy/clippy_lints/src/returns.rs | 2 +- .../src/significant_drop_tightening.rs | 2 +- .../clippy_lints/src/trailing_empty_array.rs | 2 +- .../clippy_lints/src/transmute/eager_transmute.rs | 4 +- .../src/transmute/transmute_undefined_repr.rs | 6 +- .../clippy/clippy_lints/src/transmute/utils.rs | 9 +- .../clippy_lints/src/uninhabited_references.rs | 4 +- src/tools/clippy/clippy_utils/src/consts.rs | 12 +-- src/tools/clippy/clippy_utils/src/eager_or_lazy.rs | 2 +- src/tools/clippy/clippy_utils/src/hir_utils.rs | 6 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 10 +- src/tools/clippy/clippy_utils/src/ty.rs | 17 +-- .../miri/src/borrow_tracker/stacked_borrows/mod.rs | 2 +- .../miri/src/borrow_tracker/tree_borrows/mod.rs | 2 +- src/tools/miri/src/eval.rs | 14 ++- src/tools/miri/src/helpers.rs | 4 +- src/tools/miri/src/machine.rs | 4 +- 240 files changed, 1739 insertions(+), 1340 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 51c2282422e..2afd52964dc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -682,8 +682,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // Normalize before comparing to see through type aliases and projections. let old_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, generic_args); let new_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, new_args); - if let Ok(old_ty) = tcx.try_normalize_erasing_regions(self.param_env, old_ty) - && let Ok(new_ty) = tcx.try_normalize_erasing_regions(self.param_env, new_ty) + if let Ok(old_ty) = + tcx.try_normalize_erasing_regions(self.infcx.typing_env(self.param_env), old_ty) + && let Ok(new_ty) = tcx.try_normalize_erasing_regions( + self.infcx.typing_env(self.param_env), + new_ty, + ) { old_ty == new_ty } else { @@ -3831,11 +3835,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if tcx.is_diagnostic_item(sym::deref_method, method_did) { let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| { - Instance::try_resolve(tcx, self.param_env, deref_target, method_args) - .transpose() + Instance::try_resolve( + tcx, + self.infcx.typing_env(self.param_env), + deref_target, + method_args, + ) + .transpose() }); if let Some(Ok(instance)) = deref_target { - let deref_target_ty = instance.ty(tcx, self.param_env); + let deref_target_ty = instance.ty(tcx, self.infcx.typing_env(self.param_env)); err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`")); err.span_note(tcx.def_span(instance.def_id()), "deref defined here"); } diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 0797bb49bf9..6c63da819c7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -864,7 +864,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let kind = call_kind( self.infcx.tcx, - self.param_env, + self.infcx.typing_env(self.param_env), method_did, method_args, *fn_span, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 807b5576976..d4660d8af43 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -952,7 +952,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Ok(Some(instance)) = ty::Instance::try_resolve( tcx, - self.param_env, + self.infcx.typing_env(self.param_env), *fn_did, self.infcx.resolve_vars_if_possible(args), ) { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 0fe6a4b5fce..ac0219684d8 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1527,7 +1527,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // The signature in this call can reference region variables, // so erase them before calling a query. let output_ty = self.tcx().erase_regions(sig.output()); - if !output_ty.is_privately_uninhabited(self.tcx(), self.param_env) { + if !output_ty + .is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.param_env)) + { span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig); } } diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index f647ee36c48..7dd2139cf90 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -376,7 +376,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let instance = if let ty::FnDef(def_id, fn_args) = *func.layout().ty.kind() { let instance = ty::Instance::expect_resolve( fx.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, fn_args, source_info.span, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index da3818ca25e..1b91d251bfd 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -666,7 +666,7 @@ fn codegen_stmt<'tcx>( let func_ref = fx.get_function_ref( Instance::resolve_for_fn_ptr( fx.tcx, - ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ) @@ -841,14 +841,18 @@ fn codegen_stmt<'tcx>( lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); } Rvalue::NullaryOp(ref null_op, ty) => { - assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all())); + assert!(lval.layout().ty.is_sized(fx.tcx, ty::ParamEnv::reveal_all())); let layout = fx.layout_of(fx.monomorphize(ty)); let val = match null_op { NullOp::SizeOf => layout.size.bytes(), NullOp::AlignOf => layout.align.abi.bytes(), NullOp::OffsetOf(fields) => fx .tcx - .offset_of_subfield(ParamEnv::reveal_all(), layout, fields.iter()) + .offset_of_subfield( + ty::TypingEnv::fully_monomorphized(), + layout, + fields.iter(), + ) .bytes(), NullOp::UbChecks => { let val = fx.tcx.sess.ub_checks(); diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 27e71b92561..add081bc795 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -103,11 +103,11 @@ fn clif_pair_type_from_ty<'tcx>( /// Is a pointer to this type a wide ptr? pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - if ty.is_sized(tcx, ParamEnv::reveal_all()) { + if ty.is_sized(tcx, ty::ParamEnv::reveal_all()) { return false; } - let tail = tcx.struct_tail_for_codegen(ty, ParamEnv::reveal_all()); + let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized()); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, @@ -339,9 +339,9 @@ impl<'tcx> rustc_abi::HasDataLayout for FunctionCx<'_, '_, 'tcx> { } } -impl<'tcx> layout::HasParamEnv<'tcx> for FunctionCx<'_, '_, 'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - ParamEnv::reveal_all() +impl<'tcx> layout::HasTypingEnv<'tcx> for FunctionCx<'_, '_, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } @@ -358,7 +358,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { { self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value), ) } @@ -497,9 +497,9 @@ impl<'tcx> rustc_abi::HasDataLayout for RevealAllLayoutCx<'tcx> { } } -impl<'tcx> layout::HasParamEnv<'tcx> for RevealAllLayoutCx<'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - ParamEnv::reveal_all() +impl<'tcx> layout::HasTypingEnv<'tcx> for RevealAllLayoutCx<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index ab78584332a..5311547309c 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -78,7 +78,7 @@ pub(crate) fn eval_mir_constant<'tcx>( let cv = fx.monomorphize(constant.const_); // This cannot fail because we checked all required_consts in advance. let val = cv - .eval(fx.tcx, ty::ParamEnv::reveal_all(), constant.span) + .eval(fx.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) .expect("erroneous constant missed by mono item collection"); (val, cv.ty()) } @@ -265,8 +265,13 @@ fn data_id_for_static( assert!(!definition); assert!(!tcx.is_mutable_static(def_id)); - let ty = instance.ty(tcx, ParamEnv::reveal_all()); - let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes(); + let ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized()); + let align = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + .unwrap() + .align + .pref + .bytes(); let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index 9025ea97b81..f3a8623e216 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -210,7 +210,7 @@ impl DebugContext { type_names::push_generic_params( tcx, - tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args), + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args), &mut name, ); @@ -275,8 +275,10 @@ impl DebugContext { let span = tcx.def_span(def_id); let (file_id, line, _column) = self.get_span_loc(tcx, span, span); - let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::ParamEnv::reveal_all()); - let static_layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(static_type)).unwrap(); + let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::TypingEnv::fully_monomorphized()); + let static_layout = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(static_type)) + .unwrap(); // FIXME use the actual type layout let type_id = self.debug_type(tcx, type_dbg, static_type); diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index a3f816f70a9..0df1a30fc0a 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -92,7 +92,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( fx.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ) @@ -227,11 +227,11 @@ pub(crate) fn codegen_naked_asm<'tcx>( InlineAsmOperand::Const { ref value } => { let cv = instance.instantiate_mir_and_normalize_erasing_regions( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value.const_), ); let const_value = cv - .eval(tcx, ty::ParamEnv::reveal_all(), value.span) + .eval(tcx, ty::TypingEnv::fully_monomorphized(), value.span) .expect("erroneous constant missed by mono item collection"); let value = rustc_codegen_ssa::common::asm_const_to_str( @@ -250,13 +250,13 @@ pub(crate) fn codegen_naked_asm<'tcx>( let const_ = instance.instantiate_mir_and_normalize_erasing_regions( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value.const_), ); if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index b92885cc1a7..1afe252ff04 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -20,7 +20,7 @@ mod simd; use cranelift_codegen::ir::AtomicRmwOp; use rustc_middle::ty; use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement}; +use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{Symbol, sym}; @@ -682,7 +682,10 @@ fn codegen_regular_intrinsic_call<'tcx>( if let Some(requirement) = requirement { let do_panic = !fx .tcx - .check_validity_requirement((requirement, fx.param_env().and(ty))) + .check_validity_requirement(( + requirement, + ty::TypingEnv::fully_monomorphized().as_query_input(ty), + )) .expect("expect to have layout during codegen"); if do_panic { @@ -741,7 +744,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let const_val = fx .tcx - .const_eval_instance(ParamEnv::reveal_all(), instance, source_info.span) + .const_eval_instance(ty::ParamEnv::reveal_all(), instance, source_info.span) .unwrap(); let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty); ret.write_cvalue(fx, val); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index b506b1f5731..e6f6ae30581 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -98,7 +98,7 @@ mod prelude { pub(crate) use rustc_middle::mir::{self, *}; pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; pub(crate) use rustc_middle::ty::{ - self, FloatTy, Instance, InstanceKind, IntTy, ParamEnv, Ty, TyCtxt, UintTy, + self, FloatTy, Instance, InstanceKind, IntTy, Ty, TyCtxt, UintTy, }; pub(crate) use rustc_span::Span; diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index df92bc58bf5..2ee4ff5cec7 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -49,7 +49,7 @@ pub(crate) fn maybe_create_entry_wrapper( // regions must appear in the argument // listing. let main_ret_ty = tcx.normalize_erasing_regions( - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), main_ret_ty.no_bound_vars().unwrap(), ); @@ -113,7 +113,7 @@ pub(crate) fn maybe_create_entry_wrapper( .unwrap(); let report = Instance::expect_resolve( tcx, - ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), report.def_id, tcx.mk_args(&[GenericArg::from(main_ret_ty)]), DUMMY_SP, @@ -139,7 +139,7 @@ pub(crate) fn maybe_create_entry_wrapper( let start_def_id = tcx.require_lang_item(LangItem::Start, None); let start_instance = Instance::expect_resolve( tcx, - ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), start_def_id, tcx.mk_args(&[main_ret_ty.into()]), DUMMY_SP, diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 336934354e1..2843e5bbdfb 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -3,6 +3,7 @@ //! [`PointerCoercion::Unsize`]: `rustc_middle::ty::adjustment::PointerCoercion::Unsize` use rustc_codegen_ssa::base::validate_trivial_unsize; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use crate::base::codegen_panic_nounwind; @@ -23,7 +24,7 @@ pub(crate) fn unsized_info<'tcx>( old_info: Option, ) -> Value { let (source, target) = - fx.tcx.struct_lockstep_tails_for_codegen(source, target, ParamEnv::reveal_all()); + fx.tcx.struct_lockstep_tails_for_codegen(source, target, fx.typing_env()); match (&source.kind(), &target.kind()) { (&ty::Array(_, len), &ty::Slice(_)) => fx.bcx.ins().iconst( fx.pointer_type, diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 900d7e69714..6676e684ca0 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -4,6 +4,7 @@ use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir::immediates::Offset32; use cranelift_frontend::Variable; use rustc_middle::ty::FnSig; +use rustc_middle::ty::layout::HasTypingEnv; use crate::prelude::*; @@ -884,19 +885,17 @@ pub(crate) fn assert_assignable<'tcx>( assert_assignable(fx, *a, *b, limit - 1); } (ty::FnPtr(..), ty::FnPtr(..)) => { - let from_sig = fx.tcx.normalize_erasing_late_bound_regions( - ParamEnv::reveal_all(), - from_ty.fn_sig(fx.tcx), - ); + let from_sig = fx + .tcx + .normalize_erasing_late_bound_regions(fx.typing_env(), from_ty.fn_sig(fx.tcx)); let FnSig { inputs_and_output: types_from, c_variadic: c_variadic_from, safety: unsafety_from, abi: abi_from, } = from_sig; - let to_sig = fx - .tcx - .normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to_ty.fn_sig(fx.tcx)); + let to_sig = + fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to_ty.fn_sig(fx.tcx)); let FnSig { inputs_and_output: types_to, c_variadic: c_variadic_to, @@ -932,9 +931,8 @@ pub(crate) fn assert_assignable<'tcx>( (&ty::Dynamic(from_traits, _, _from_kind), &ty::Dynamic(to_traits, _, _to_kind)) => { // FIXME(dyn-star): Do the right thing with DynKinds for (from, to) in from_traits.iter().zip(to_traits) { - let from = - fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from); - let to = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to); + let from = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), from); + let to = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to); assert_eq!( from, to, "Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}", diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index e6ae7cf174d..9a142326ad1 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -24,9 +24,9 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, }; -use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::def_id::DefId; use rustc_target::abi::call::FnAbi; @@ -2319,9 +2319,9 @@ impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - self.cx.param_env() +impl<'tcx> HasTypingEnv<'tcx> for Builder<'_, '_, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.cx.typing_env() } } diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 07c7a54de1c..6dc2f4ed668 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -215,7 +215,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let gcc_type = if nested { self.type_i8() } else { - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let ty = instance.ty(self.tcx, ty::TypingEnv::fully_monomorphized()); self.layout_of(ty).gcc_type(self) }; diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 707b35967a6..3846d025537 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -11,10 +11,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::span_bug; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, + FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, }; -use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; @@ -144,7 +144,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { supports_f128_type: bool, ) -> Self { let create_type = |ctype, rust_type| { - let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap(); + let layout = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type)) + .unwrap(); let align = layout.align.abi.bytes(); #[cfg(feature = "master")] { @@ -459,7 +461,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { Some(def_id) if !wants_msvc_seh(self.sess()) => { let instance = ty::Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + self.typing_env(), def_id, ty::List::empty(), DUMMY_SP, @@ -583,9 +585,9 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { } } -impl<'tcx, 'gcc> HasParamEnv<'tcx> for CodegenCx<'gcc, 'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - ParamEnv::reveal_all() +impl<'tcx, 'gcc> HasTypingEnv<'tcx> for CodegenCx<'gcc, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index 5ca440f4c9b..02b760dc733 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -5,7 +5,7 @@ use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp}; -use rustc_middle::ty::{ParamEnv, Ty}; +use rustc_middle::ty::{self, Ty}; use rustc_target::abi::Endian; use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}; use rustc_target::spec; @@ -380,7 +380,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow"); let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]); - let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ret_ty)).unwrap(); + let layout = self + .tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty)) + .unwrap(); let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) }; let mut fn_abi = FnAbi { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 225f294e1e4..69326f409bb 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -21,7 +21,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, MiscCodegenMethods}; use rustc_middle::bug; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; use rustc_target::abi::HasDataLayout; @@ -107,7 +107,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc span: Span, ) -> Result<(), Instance<'tcx>> { let tcx = self.tcx; - let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let callee_ty = instance.ty(tcx, self.typing_env()); let (def_id, fn_args) = match *callee_ty.kind() { ty::FnDef(def_id, fn_args) => (def_id, fn_args), @@ -115,7 +115,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc }; let sig = callee_ty.fn_sig(tcx); - let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = tcx.item_name(def_id); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 43dbfafa871..604678a9af4 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -55,8 +55,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } let tcx = bx.tcx(); - let sig = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx)); + let sig = tcx.normalize_erasing_late_bound_regions( + ty::TypingEnv::fully_monomorphized(), + callee_ty.fn_sig(tcx), + ); let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { @@ -478,7 +480,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *in_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { span, @@ -493,7 +495,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *out_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { span, diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index b7b282bf2a6..239902df7f0 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::{Linkage, Visibility}; -use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use crate::context::CodegenCx; @@ -27,11 +27,8 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out // the gcc type from the actual evaluated initializer. - let ty = if nested { - self.tcx.types.unit - } else { - instance.ty(self.tcx, ty::ParamEnv::reveal_all()) - }; + let ty = + if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) }; let gcc_type = self.layout_of(ty).gcc_type(self); let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index ac76b781218..b5bb7630ca6 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -14,7 +14,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers, TyAndLayout, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; @@ -81,9 +81,9 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> { } } -impl<'tcx> ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.cx.param_env() +impl<'tcx> ty::layout::HasTypingEnv<'tcx> for Builder<'_, '_, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.cx.typing_env() } } @@ -472,7 +472,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { #[instrument(level = "trace", skip(self))] fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> { if place.layout.is_unsized() { - let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.param_env()); + let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.typing_env()); if matches!(tail.kind(), ty::Foreign(..)) { // Unsized locals and, at least conceptually, even unsized arguments must be copied // around, which requires dynamically determining their size. Therefore, we cannot diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index dcea9d3b391..e0a2de3366c 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -5,7 +5,7 @@ //! closure. use rustc_codegen_ssa::common; -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use tracing::debug; @@ -28,12 +28,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t } let sym = tcx.symbol_name(instance).name; - debug!( - "get_fn({:?}: {:?}) => {}", - instance, - instance.ty(cx.tcx(), ty::ParamEnv::reveal_all()), - sym - ); + debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx(), cx.typing_env()), sym); let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 7ab4f45cd73..6f5ffbb4b34 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -13,8 +13,8 @@ use rustc_middle::mir::interpret::{ read_target_uint, }; use rustc_middle::mir::mono::MonoItem; -use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, Instance}; +use rustc_middle::ty::Instance; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::{bug, span_bug}; use rustc_session::config::Lto; use tracing::{debug, instrument, trace}; @@ -244,7 +244,7 @@ impl<'ll> CodegenCx<'ll, '_> { let llty = if nested { self.type_i8() } else { - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let ty = instance.ty(self.tcx, self.typing_env()); trace!(?ty); self.layout_of(ty).llvm_type(self) }; diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 3a7c7efe03b..841c110b3c8 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -15,7 +15,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -658,7 +658,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { let llfn = match tcx.lang_items().eh_personality() { Some(def_id) if name.is_none() => self.get_fn_addr(ty::Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + self.typing_env(), def_id, ty::List::empty(), DUMMY_SP, @@ -1162,9 +1162,9 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for CodegenCx<'_, 'tcx> { } } -impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - ty::ParamEnv::reveal_all() +impl<'tcx, 'll> HasTypingEnv<'tcx> for CodegenCx<'ll, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 0f1909486ec..4a68bdea85e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_index::Idx; use rustc_index::bit_set::BitSet; use rustc_middle::mir::{Body, SourceScope}; -use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv}; use rustc_middle::ty::{self, Instance}; use rustc_session::config::DebugInfo; use rustc_span::BytePos; @@ -118,7 +118,7 @@ fn make_mir_scope<'ll, 'tcx>( // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. let callee = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, - ty::ParamEnv::reveal_all(), + cx.typing_env(), ty::EarlyBinder::bind(callee), ); debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 151923a3bd2..ef16e5bb459 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -11,10 +11,9 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{ - self, AdtKind, CoroutineArgsExt, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, - Visibility, + self, AdtKind, CoroutineArgsExt, Instance, PolyExistentialTraitRef, Ty, TyCtxt, Visibility, }; use rustc_session::config::{self, DebugInfo, Lto}; use rustc_span::symbol::Symbol; @@ -301,9 +300,8 @@ fn build_subroutine_type_di_node<'ll, 'tcx>( .insert(unique_type_id, recursion_marker_type_di_node(cx)); let fn_ty = unique_type_id.expect_ty(); - let signature = cx - .tcx - .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), fn_ty.fn_sig(cx.tcx)); + let signature = + cx.tcx.normalize_erasing_late_bound_regions(cx.typing_env(), fn_ty.fn_sig(cx.tcx)); let signature_di_nodes: SmallVec<_> = iter::once( // return type @@ -1109,9 +1107,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( } }; - assert!( - up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) - ); + assert!(up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(cx.typing_env(), t))); let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id); let layout = cx.layout_of(closure_or_coroutine_ty); @@ -1272,8 +1268,7 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( let template_params: SmallVec<_> = iter::zip(args, names) .filter_map(|(kind, name)| { kind.as_type().map(|ty| { - let actual_type = - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); + let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); let actual_type_di_node = type_di_node(cx, actual_type); let name = name.as_str(); unsafe { @@ -1341,7 +1336,7 @@ pub(crate) fn build_global_var_di_node<'ll>( if nested { return; } - let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); + let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, cx.typing_env()); let type_di_node = type_di_node(cx, variable_type); let var_name = tcx.item_name(def_id); let var_name = var_name.as_str(); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 5120b63d173..4e461476040 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; use rustc_middle::bug; -use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, PolyExistentialTraitRef, Ty, TyCtxt}; use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata}; use crate::common::{AsCCharPtr, CodegenCx}; @@ -49,12 +49,15 @@ pub(super) enum UniqueTypeId<'tcx> { impl<'tcx> UniqueTypeId<'tcx> { pub(crate) fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self { - assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)); + assert_eq!(t, tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), t)); UniqueTypeId::Ty(t, private::HiddenZst) } pub(crate) fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self { - assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + assert_eq!( + enum_ty, + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty) + ); UniqueTypeId::VariantPart(enum_ty, private::HiddenZst) } @@ -63,7 +66,10 @@ impl<'tcx> UniqueTypeId<'tcx> { enum_ty: Ty<'tcx>, variant_idx: VariantIdx, ) -> Self { - assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + assert_eq!( + enum_ty, + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty) + ); UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst) } @@ -72,7 +78,10 @@ impl<'tcx> UniqueTypeId<'tcx> { enum_ty: Ty<'tcx>, variant_idx: VariantIdx, ) -> Self { - assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + assert_eq!( + enum_ty, + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty) + ); UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst) } @@ -81,10 +90,13 @@ impl<'tcx> UniqueTypeId<'tcx> { self_type: Ty<'tcx>, implemented_trait: Option>, ) -> Self { - assert_eq!(self_type, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type)); + assert_eq!( + self_type, + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), self_type) + ); assert_eq!( implemented_trait, - tcx.normalize_erasing_regions(ParamEnv::reveal_all(), implemented_trait) + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), implemented_trait) ); UniqueTypeId::VTableTy(self_type, implemented_trait, private::HiddenZst) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 89492e4b9fe..4b650b00bee 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -15,8 +15,8 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_index::IndexVec; use rustc_middle::mir; -use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, GenericArgsRef, Instance, ParamEnv, Ty, TypeVisitableExt}; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; +use rustc_middle::ty::{self, GenericArgsRef, Instance, Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::Symbol; @@ -344,7 +344,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { type_names::push_generic_params( tcx, - tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args), + tcx.normalize_erasing_regions(self.typing_env(), args), &mut name, ); @@ -481,8 +481,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { iter::zip(args, names) .filter_map(|(kind, name)| { kind.as_type().map(|ty| { - let actual_type = - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); + let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); let actual_type_metadata = type_di_node(cx, actual_type); let name = name.as_str(); unsafe { @@ -526,7 +525,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { if cx.tcx.trait_id_of_impl(impl_def_id).is_none() { let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, - ty::ParamEnv::reveal_all(), + cx.typing_env(), cx.tcx.type_of(impl_def_id), ); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index 960487ada16..6e841293477 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -1,7 +1,7 @@ // Utility Functions. use rustc_hir::def_id::DefId; -use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Ty}; use tracing::trace; @@ -62,7 +62,7 @@ pub(crate) fn wide_pointer_kind<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, pointee_ty: Ty<'tcx>, ) -> Option { - let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env()); + let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.typing_env()); let layout = cx.layout_of(pointee_tail_ty); trace!( "wide_pointer_kind: {:?} has layout {:?} (is_unsized? {})", diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index b56f464975d..da7f94e8cf7 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -10,7 +10,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::*; use rustc_hir as hir; use rustc_middle::mir::BinOp; -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; @@ -163,14 +163,14 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { span: Span, ) -> Result<(), ty::Instance<'tcx>> { let tcx = self.tcx; - let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let callee_ty = instance.ty(tcx, self.typing_env()); let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else { bug!("expected fn item type, found {}", callee_ty); }; let sig = callee_ty.fn_sig(tcx); - let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = tcx.item_name(def_id); @@ -1152,8 +1152,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } let tcx = bx.tcx(); - let sig = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx)); + let sig = tcx.normalize_erasing_late_bound_regions(bx.typing_env(), callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); // Sanity-check: all vector arguments must be immediates. @@ -2187,7 +2186,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( match in_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + bx.tcx.normalize_erasing_regions(bx.typing_env(), ty) }); require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { span, @@ -2202,7 +2201,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( match out_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + bx.tcx.normalize_erasing_regions(bx.typing_env(), ty) }); require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { span, diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index ea8857b4739..33789c6261f 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -3,7 +3,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::mir::mono::{Linkage, Visibility}; -use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use rustc_session::config::CrateType; use rustc_target::spec::RelocModel; @@ -26,11 +26,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure // out the llvm type from the actual evaluated initializer. - let ty = if nested { - self.tcx.types.unit - } else { - instance.ty(self.tcx, ty::ParamEnv::reveal_all()) - }; + let ty = + if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) }; let llty = self.layout_of(ty).llvm_type(self); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 850d36872dd..d9152c5d080 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -595,8 +595,10 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( let (conv, args) = instance .map(|i| { - tcx.fn_abi_of_instance(ty::ParamEnv::reveal_all().and((i, ty::List::empty()))) - .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed")) + tcx.fn_abi_of_instance( + ty::TypingEnv::fully_monomorphized().as_query_input((i, ty::List::empty())), + ) + .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed")) }) .map(|fnabi| (fnabi.conv, &fnabi.args[..])) .unwrap_or((Conv::Rust, &[])); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index ef95ab94062..c8b3b30218a 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -21,7 +21,7 @@ use rustc_middle::middle::{exported_symbols, lang_items}; use rustc_middle::mir::BinOp; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::query::Providers; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode}; use rustc_session::Session; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; @@ -165,7 +165,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) -> Bx::Value { let cx = bx.cx(); let (source, target) = - cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env()); + cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.typing_env()); match (source.kind(), target.kind()) { (&ty::Array(_, len), &ty::Slice(_)) => cx.const_usize( len.try_to_target_usize(cx.tcx()).expect("expected monomorphic const in codegen"), @@ -466,10 +466,9 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // late-bound regions, since late-bound // regions must appear in the argument // listing. - let main_ret_ty = cx.tcx().normalize_erasing_regions( - ty::ParamEnv::reveal_all(), - main_ret_ty.no_bound_vars().unwrap(), - ); + let main_ret_ty = cx + .tcx() + .normalize_erasing_regions(cx.typing_env(), main_ret_ty.no_bound_vars().unwrap()); let Some(llfn) = cx.declare_c_main(llfty) else { // FIXME: We should be smart and show a better diagnostic here. @@ -495,7 +494,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None); let start_instance = ty::Instance::expect_resolve( cx.tcx(), - ty::ParamEnv::reveal_all(), + cx.typing_env(), start_def_id, cx.tcx().mk_args(&[main_ret_ty.into()]), DUMMY_SP, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 27bc58516c0..6c4f6d37972 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -21,9 +21,7 @@ use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathD use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability}; use rustc_middle::bug; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; -use rustc_middle::ty::{ - self, ExistentialProjection, GenericArgKind, GenericArgsRef, ParamEnv, Ty, TyCtxt, -}; +use rustc_middle::ty::{self, ExistentialProjection, GenericArgKind, GenericArgsRef, Ty, TyCtxt}; use smallvec::SmallVec; use crate::debuginfo::wants_c_like_enum_debuginfo; @@ -82,7 +80,7 @@ fn push_debuginfo_type_name<'tcx>( ty::Adt(def, args) => { // `layout_for_cpp_like_fallback` will be `Some` if we want to use the fallback encoding. let layout_for_cpp_like_fallback = if cpp_like_debuginfo && def.is_enum() { - match tcx.layout_of(ParamEnv::reveal_all().and(t)) { + match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(t)) { Ok(layout) => { if !wants_c_like_enum_debuginfo(tcx, layout) { Some(layout) @@ -248,8 +246,10 @@ fn push_debuginfo_type_name<'tcx>( }; if let Some(principal) = trait_data.principal() { - let principal = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal); + let principal = tcx.normalize_erasing_late_bound_regions( + ty::TypingEnv::fully_monomorphized(), + principal, + ); push_item_name(tcx, principal.def_id, qualified, output); let principal_has_generic_params = push_generic_params_internal(tcx, principal.args, output, visited); @@ -350,8 +350,10 @@ fn push_debuginfo_type_name<'tcx>( return; } - let sig = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx)); + let sig = tcx.normalize_erasing_late_bound_regions( + ty::TypingEnv::fully_monomorphized(), + t.fn_sig(tcx), + ); if cpp_like_debuginfo { // Format as a C++ function pointer: return_type (*)(params...) @@ -415,7 +417,8 @@ fn push_debuginfo_type_name<'tcx>( // In the case of cpp-like debuginfo, the name additionally gets wrapped inside of // an artificial `enum2$<>` type, as defined in msvc_enum_fallback(). if cpp_like_debuginfo && t.is_coroutine() { - let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).unwrap(); + let ty_and_layout = + tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(t)).unwrap(); msvc_enum_fallback( tcx, ty_and_layout, @@ -529,8 +532,8 @@ pub fn compute_debuginfo_vtable_name<'tcx>( } if let Some(trait_ref) = trait_ref { - let trait_ref = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref); + let trait_ref = tcx + .normalize_erasing_late_bound_regions(ty::TypingEnv::fully_monomorphized(), trait_ref); push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name); visited.clear(); push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited); @@ -639,7 +642,7 @@ fn push_generic_params_internal<'tcx>( output: &mut String, visited: &mut FxHashSet>, ) -> bool { - assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args)); + assert_eq!(args, tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args)); let mut args = args.non_erasable_generics().peekable(); if args.peek().is_none() { return false; @@ -678,14 +681,14 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S // FIXME: directly extract the bits from a valtree instead of evaluating an // already evaluated `Const` in order to get the bits. let bits = ct - .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected monomorphic const in codegen"); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; write!(output, "{val}") } ty::Uint(_) => { let val = ct - .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected monomorphic const in codegen"); write!(output, "{val}") } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 097d37bb70c..e3ed12b5ce6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -777,7 +777,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let do_panic = !bx .tcx() - .check_validity_requirement((requirement, bx.param_env().and(ty))) + .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty))) .expect("expect to have layout during codegen"); let layout = bx.layout_of(ty); @@ -848,14 +848,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (instance, mut llfn) = match *callee.layout.ty.kind() { ty::FnDef(def_id, args) => ( Some( - ty::Instance::expect_resolve( - bx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - args, - fn_span, - ) - .polymorphize(bx.tcx()), + ty::Instance::expect_resolve(bx.tcx(), bx.typing_env(), def_id, args, fn_span) + .polymorphize(bx.tcx()), ), None, ), @@ -1191,7 +1185,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( bx.tcx(), - ty::ParamEnv::reveal_all(), + bx.typing_env(), def_id, args, ) diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 54b9c9cc89f..7676e1e171a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -1,6 +1,6 @@ use rustc_abi::BackendRepr; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::ty::layout::HasTyCtxt; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir, span_bug}; @@ -24,7 +24,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // `MirUsedCollector` visited all required_consts before codegen began, so if we got here // there can be no more constants that fail to evaluate. self.monomorphize(constant.const_) - .eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), constant.span) + .eval(self.cx.tcx(), self.cx.typing_env(), constant.span) .expect("erroneous constant missed by mono item collection") } @@ -57,7 +57,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { other => span_bug!(constant.span, "{other:#?}"), }; let uv = self.monomorphize(uv); - self.cx.tcx().const_eval_resolve_for_typeck(ty::ParamEnv::reveal_all(), uv, constant.span) + self.cx.tcx().const_eval_resolve_for_typeck(self.cx.typing_env(), uv, constant.span) } /// process constant containing SIMD shuffle indices & constant vectors diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 2a1b9e28c1e..c35d0b90706 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -59,14 +59,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { llresult: Bx::Value, span: Span, ) -> Result<(), ty::Instance<'tcx>> { - let callee_ty = instance.ty(bx.tcx(), ty::ParamEnv::reveal_all()); + let callee_ty = instance.ty(bx.tcx(), bx.typing_env()); let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else { bug!("expected fn item type, found {}", callee_ty); }; let sig = callee_ty.fn_sig(bx.tcx()); - let sig = bx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = bx.tcx().normalize_erasing_late_bound_regions(bx.typing_env(), sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = bx.tcx().item_name(def_id); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index f19e3b72141..0cbc5c45736 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -4,7 +4,7 @@ use rustc_index::IndexVec; use rustc_index::bit_set::BitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::{UnwindTerminateReason, traversal}; -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::{bug, mir, span_bug}; use rustc_target::callconv::{FnAbi, PassMode}; @@ -128,7 +128,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { debug!("monomorphize: self.instance={:?}", self.instance); self.instance.instantiate_mir_and_normalize_erasing_regions( self.cx.tcx(), - ty::ParamEnv::reveal_all(), + self.cx.typing_env(), ty::EarlyBinder::bind(value), ) } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 0e1cd662f91..f63b2d139c5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -474,7 +474,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ty::FnDef(def_id, args) => { let instance = ty::Instance::resolve_for_fn_ptr( bx.tcx(), - ty::ParamEnv::reveal_all(), + bx.typing_env(), def_id, args, ) @@ -709,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::NullOp::OffsetOf(fields) => { let val = bx .tcx() - .offset_of_subfield(bx.param_env(), layout, fields.iter()) + .offset_of_subfield(bx.typing_env(), layout, fields.iter()) .bytes(); bx.cx().const_usize(val) } @@ -727,7 +727,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::ThreadLocalRef(def_id) => { assert!(bx.cx().tcx().is_static(def_id)); - let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id)); + let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id, bx.typing_env())); let static_ = if !def_id.is_local() && bx.cx().tcx().needs_thread_local_shim(def_id) { let instance = ty::Instance { diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 44ba2262149..3810c609fd4 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -1,6 +1,6 @@ use rustc_abi::{AddressSpace, Float, Integer}; use rustc_middle::bug; -use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi, Reg}; @@ -41,7 +41,7 @@ pub trait BaseTypeCodegenMethods<'tcx>: BackendTypes { } pub trait DerivedTypeCodegenMethods<'tcx>: - BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> + BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> + HasTypingEnv<'tcx> { fn type_int(&self) -> Self::Type { match &self.sess().target.c_int_width[..] { @@ -74,7 +74,7 @@ pub trait DerivedTypeCodegenMethods<'tcx>: } fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool { - ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all()) + ty.needs_drop(self.tcx(), self.typing_env()) } fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { @@ -86,12 +86,11 @@ pub trait DerivedTypeCodegenMethods<'tcx>: } fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { - let param_env = ty::ParamEnv::reveal_all(); - if ty.is_sized(self.tcx(), param_env) { + if ty.is_sized(self.tcx(), self.param_env()) { return false; } - let tail = self.tcx().struct_tail_for_codegen(ty, param_env); + let tail = self.tcx().struct_tail_for_codegen(ty, self.typing_env()); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, @@ -101,7 +100,10 @@ pub trait DerivedTypeCodegenMethods<'tcx>: } impl<'tcx, T> DerivedTypeCodegenMethods<'tcx> for T where - Self: BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> + Self: BaseTypeCodegenMethods<'tcx> + + MiscCodegenMethods<'tcx> + + HasTyCtxt<'tcx> + + HasTypingEnv<'tcx> { } diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index ffe32acb316..50e8a168eeb 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -388,7 +388,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { return false; } - let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx)); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let body_id = self.body.source.def_id().expect_local(); @@ -398,11 +398,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { ty::BoundConstness::Const } }; - let const_conditions = ocx.normalize( - &ObligationCause::misc(call_span, body_id), - self.param_env, - const_conditions, - ); + let const_conditions = + ocx.normalize(&ObligationCause::misc(call_span, body_id), param_env, const_conditions); ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, span)| { Obligation::new( tcx, @@ -411,7 +408,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { body_id, ObligationCauseCode::WhereClause(callee, span), ), - self.param_env, + param_env, trait_ref.to_host_effect_clause(tcx, host_polarity), ) })); diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index ebdd55a4f70..80d3c6448aa 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -24,17 +24,15 @@ mod resolver; pub struct ConstCx<'mir, 'tcx> { pub body: &'mir mir::Body<'tcx>, pub tcx: TyCtxt<'tcx>, - pub param_env: ty::ParamEnv<'tcx>, + pub typing_env: ty::TypingEnv<'tcx>, pub const_kind: Option, } impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self { - let def_id = body.source.def_id().expect_local(); - let param_env = tcx.param_env(def_id); - + let typing_env = body.typing_env(tcx); let const_kind = tcx.hir().body_const_context(body.source.def_id().expect_local()); - ConstCx { body, tcx, param_env, const_kind } + ConstCx { body, tcx, typing_env, const_kind } } pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> { diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index ca95e42dd2b..8ba6b89aad4 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -120,7 +120,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { #[allow(rustc::untranslatable_diagnostic)] fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> { let FnCallNonConst { callee, args, span, call_source } = *self; - let ConstCx { tcx, param_env, .. } = *ccx; + let ConstCx { tcx, typing_env, .. } = *ccx; let caller = ccx.def_id(); let diag_trait = |err, self_ty: Ty<'_>, trait_id| { @@ -146,13 +146,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { } } ty::Adt(..) => { + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); - - let infcx = tcx.infer_ctxt().build(ccx.body.typing_mode(tcx)); let mut selcx = SelectionContext::new(&infcx); let implsrc = selcx.select(&obligation); - if let Ok(Some(ImplSource::UserDefined(data))) = implsrc { // FIXME(const_trait_impl) revisit this if !tcx.is_const_trait_impl(data.impl_def_id) { @@ -166,7 +164,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { }; let call_kind = - call_kind(tcx, ccx.param_env, callee, args, span, call_source.from_hir_call(), None); + call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None); debug!(?call_kind); diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index 0173a528c22..f6eb130fbd3 100644 --- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs @@ -32,17 +32,15 @@ pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool { /// This is separate from the rest of the const checking logic because it must run after drop /// elaboration. pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { - let def_id = body.source.def_id().expect_local(); - let const_kind = tcx.hir().body_const_context(def_id); - if const_kind.is_none() { + let ccx = ConstCx::new(tcx, body); + if ccx.const_kind.is_none() { return; } - if tcx.has_attr(def_id, sym::rustc_do_not_const_check) { + if tcx.has_attr(body.source.def_id(), sym::rustc_do_not_const_check) { return; } - let ccx = ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def_id) }; if !checking_enabled(&ccx) { return; } diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 29a08579175..bc416acc58d 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -106,20 +106,24 @@ impl Qualif for HasMutInterior { // Instead we invoke an obligation context manually, and provide the opaque type inference settings // that allow the trait solver to just error out instead of cycling. let freeze_def_id = cx.tcx.require_lang_item(LangItem::Freeze, Some(cx.body.span)); - + // FIXME(#132279): Once we've got a typing mode which reveals opaque types using the HIR + // typeck results without causing query cycles, we should use this here instead of defining + // opaque types. + let typing_env = ty::TypingEnv { + typing_mode: ty::TypingMode::analysis_in_body( + cx.tcx, + cx.body.source.def_id().expect_local(), + ), + param_env: cx.typing_env.param_env, + }; + let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(typing_env); + let ocx = ObligationCtxt::new(&infcx); let obligation = Obligation::new( cx.tcx, ObligationCause::dummy_with_span(cx.body.span), - cx.param_env, + param_env, ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]), ); - - // FIXME(#132279): This should eventually use the already defined hidden types. - let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body( - cx.tcx, - cx.body.source.def_id().expect_local(), - )); - let ocx = ObligationCtxt::new(&infcx); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); !errors.is_empty() @@ -156,7 +160,7 @@ impl Qualif for NeedsDrop { } fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.needs_drop(cx.tcx, cx.param_env) + ty.needs_drop(cx.tcx, cx.typing_env) } fn in_adt_inherently<'tcx>( diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index 74eb6b37fbb..03624a2ce50 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -120,7 +120,10 @@ where /// /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool { - !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.param_env) + !place + .ty(self.ccx.body, self.ccx.tcx) + .ty + .is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env) } } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index a430d9dc797..ca3ee6773a0 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -221,7 +221,7 @@ pub(super) fn op_to_const<'tcx>( let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs debug_assert!( matches!( - ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.param_env).kind(), + ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(), ty::Str | ty::Slice(..), ), "`ConstValue::Slice` is for slice-tailed types only, but got {}", @@ -280,11 +280,13 @@ pub fn eval_to_const_value_raw_provider<'tcx>( // opaque types. This is needed for trivial things like `size_of`, but also for using associated // types that are not specified in the opaque type. assert_eq!(key.param_env.reveal(), Reveal::All); + let typing_env = + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: key.param_env }; // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // Catch such calls and evaluate them instead of trying to load a constant's MIR. if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def { - let ty = key.value.instance.ty(tcx, key.param_env); + let ty = key.value.instance.ty(tcx, typing_env); let ty::FnDef(_, args) = ty.kind() else { bug!("intrinsic with type {:?}", ty); }; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index f12320cb851..19c3195aaa4 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -249,9 +249,10 @@ impl<'tcx> CompileTimeInterpCx<'tcx> { } else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) { // For panic_fmt, call const_panic_fmt instead. let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None); + // FIXME(@lcnr): why does this use an empty env if we've got a `param_env` right here. let new_instance = ty::Instance::expect_resolve( *self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), const_def_id, instance.args, self.cur_span(), diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index ea88b2ed22e..64bedea3b3f 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -2,6 +2,7 @@ use rustc_abi::{BackendRepr, VariantIdx}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; +use rustc_middle::ty::solve::Reveal; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::DUMMY_SP; @@ -281,8 +282,9 @@ pub fn valtree_to_const_value<'tcx>( // the `ValTree` and using `place_projection` and `place_field` to // create inner `MPlace`s which are filled recursively. // FIXME Does this need an example? - let (param_env, ty) = param_env_ty.into_parts(); + debug_assert_eq!(param_env.reveal(), Reveal::All); + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; match *ty.kind() { ty::FnDef(..) => { @@ -302,11 +304,12 @@ pub fn valtree_to_const_value<'tcx>( let mut ecx = mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No); let imm = valtree_to_ref(&mut ecx, valtree, inner_ty); - let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap()); + let imm = + ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap()); op_to_const(&ecx, &imm.into(), /* for diagnostics */ false) } ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => { - let layout = tcx.layout_of(param_env_ty).unwrap(); + let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap(); if layout.is_zst() { // Fast path to avoid some allocations. return mir::ConstValue::ZeroSized; @@ -319,7 +322,7 @@ pub fn valtree_to_const_value<'tcx>( let branches = valtree.unwrap_branch(); // Find the non-ZST field. (There can be aligned ZST!) for (i, &inner_valtree) in branches.iter().enumerate() { - let field = layout.field(&LayoutCx::new(tcx, param_env), i); + let field = layout.field(&LayoutCx::new(tcx, typing_env), i); if !field.is_zst() { return valtree_to_const_value(tcx, param_env.and(field.ty), inner_valtree); } diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index ef0902e4226..6cfe4b21907 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -215,7 +215,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Even if `ty` is normalized, the search for the unsized tail will project // to fields, which can yield non-normalized types. So we need to provide a // normalization function. - let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty); + let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env(), ty); ty.ptr_metadata_ty(*self.tcx, normalize) }; return interp_ok(meta_ty(caller) == meta_ty(callee)); @@ -652,35 +652,35 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // Obtain the underlying trait we are working on, and the adjusted receiver argument. - let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) = - receiver_place.layout.ty.kind() - { - let recv = self.unpack_dyn_star(&receiver_place, data)?; + let (trait_, dyn_ty, adjusted_recv) = + if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() { + let recv = self.unpack_dyn_star(&receiver_place, data)?; - (data.principal(), recv.layout.ty, recv.ptr()) - } else { - // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. - // (For that reason we also cannot use `unpack_dyn_trait`.) - let receiver_tail = - self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.param_env); - let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { - span_bug!( - self.cur_span(), - "dynamic call on non-`dyn` type {}", - receiver_tail - ) + (data.principal(), recv.layout.ty, recv.ptr()) + } else { + // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. + // (For that reason we also cannot use `unpack_dyn_trait`.) + let receiver_tail = self + .tcx + .struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env()); + let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { + span_bug!( + self.cur_span(), + "dynamic call on non-`dyn` type {}", + receiver_tail + ) + }; + assert!(receiver_place.layout.is_unsized()); + + // Get the required information from the vtable. + let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; + let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; + + // It might be surprising that we use a pointer as the receiver even if this + // is a by-val case; this works because by-val passing of an unsized `dyn + // Trait` to a function is actually desugared to a pointer. + (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) }; - assert!(receiver_place.layout.is_unsized()); - - // Get the required information from the vtable. - let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; - let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; - - // It might be surprising that we use a pointer as the receiver even if this - // is a by-val case; this works because by-val passing of an unsized `dyn - // Trait` to a function is actually desugared to a pointer. - (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) - }; // Now determine the actual method to call. Usually we use the easy way of just // looking up the method at index `idx`. @@ -704,7 +704,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let concrete_method = Instance::expect_resolve_for_vtable( tcx, - self.param_env, + self.typing_env(), def_id, instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 49559059265..2d1bb5c9551 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -83,7 +83,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::FnDef(def_id, args) => { let instance = ty::Instance::resolve_for_fn_ptr( *self.tcx, - self.param_env, + self.typing_env(), def_id, args, ) @@ -384,7 +384,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { // A -> A conversion let (src_pointee_ty, dest_pointee_ty) = - self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env); + self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env()); match (src_pointee_ty.kind(), dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index ff6d5b28b3b..70a696e3e3e 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -10,9 +10,7 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, }; -use rustc_middle::ty::{ - self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypingMode, Variance, -}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypingEnv, Variance}; use rustc_middle::{mir, span_bug}; use rustc_session::Limit; use rustc_span::Span; @@ -65,12 +63,12 @@ where } } -impl<'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'tcx, M> +impl<'tcx, M> layout::HasTypingEnv<'tcx> for InterpCx<'tcx, M> where M: Machine<'tcx>, { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env() } } @@ -116,8 +114,7 @@ impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> { /// This test should be symmetric, as it is primarily about layout compatibility. pub(super) fn mir_assign_valid_types<'tcx>( tcx: TyCtxt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, src: TyAndLayout<'tcx>, dest: TyAndLayout<'tcx>, ) -> bool { @@ -125,7 +122,7 @@ pub(super) fn mir_assign_valid_types<'tcx>( // all normal lifetimes are erased, higher-ranked types with their // late-bound lifetimes are still around and can lead to type // differences. - if util::relate_types(tcx, typing_mode, param_env, Variance::Covariant, src.ty, dest.ty) { + if util::relate_types(tcx, typing_env, Variance::Covariant, src.ty, dest.ty) { // Make sure the layout is equal, too -- just to be safe. Miri really // needs layout equality. For performance reason we skip this check when // the types are equal. Equal types *can* have different layouts when @@ -145,8 +142,7 @@ pub(super) fn mir_assign_valid_types<'tcx>( #[cfg_attr(not(debug_assertions), inline(always))] pub(super) fn from_known_layout<'tcx>( tcx: TyCtxtAt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, known_layout: Option>, compute: impl FnOnce() -> InterpResult<'tcx, TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, TyAndLayout<'tcx>> { @@ -155,13 +151,7 @@ pub(super) fn from_known_layout<'tcx>( Some(known_layout) => { if cfg!(debug_assertions) { let check_layout = compute()?; - if !mir_assign_valid_types( - tcx.tcx, - typing_mode, - param_env, - check_layout, - known_layout, - ) { + if !mir_assign_valid_types(tcx.tcx, typing_env, check_layout, known_layout) { span_bug!( tcx.span, "expected type differs from actual type.\nexpected: {}\nactual: {}", @@ -211,9 +201,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - pub fn typing_mode(&self) -> TypingMode<'tcx> { + /// During CTFE we're always in `PostAnalysis` mode. + #[inline(always)] + pub fn typing_env(&self) -> ty::TypingEnv<'tcx> { debug_assert_eq!(self.param_env.reveal(), Reveal::All); - TypingMode::PostAnalysis + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } } /// Returns the span of the currently executed statement/terminator. @@ -304,13 +296,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .instance .try_instantiate_mir_and_normalize_erasing_regions( *self.tcx, - self.param_env, + self.typing_env(), ty::EarlyBinder::bind(value), ) .map_err(|_| ErrorHandled::TooGeneric(self.cur_span())) } - /// The `args` are assumed to already be in our interpreter "universe" (param_env). + /// The `args` are assumed to already be in our interpreter "universe". pub(super) fn resolve( &self, def: DefId, @@ -319,7 +311,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { trace!("resolve: {:?}, {:#?}", def, args); trace!("param_env: {:#?}", self.param_env); trace!("args: {:#?}", args); - match ty::Instance::try_resolve(*self.tcx, self.param_env, def, args) { + match ty::Instance::try_resolve(*self.tcx, self.typing_env(), def, args) { Ok(Some(instance)) => interp_ok(instance), Ok(None) => throw_inval!(TooGeneric), @@ -328,7 +320,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - /// Check if the two things are equal in the current param_env, using an infctx to get proper + /// Check if the two things are equal in the current param_env, using an infcx to get proper /// equality checks. #[instrument(level = "trace", skip(self), ret)] pub(super) fn eq_in_param_env(&self, a: T, b: T) -> bool @@ -340,14 +332,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return true; } // Slow path: spin up an inference context to check if these traits are sufficiently equal. - let infcx = self.tcx.infer_ctxt().build(self.typing_mode()); + let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env()); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy_with_span(self.cur_span()); // equate the two trait refs after normalization - let a = ocx.normalize(&cause, self.param_env, a); - let b = ocx.normalize(&cause, self.param_env, b); + let a = ocx.normalize(&cause, param_env, a); + let b = ocx.normalize(&cause, param_env, b); - if let Err(terr) = ocx.eq(&cause, self.param_env, a, b) { + if let Err(terr) = ocx.eq(&cause, param_env, a, b) { trace!(?terr); return false; } @@ -572,7 +564,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let val = if self.tcx.is_static(gid.instance.def_id()) { let alloc_id = self.tcx.reserve_and_set_static_alloc(gid.instance.def_id()); - let ty = instance.ty(self.tcx.tcx, self.param_env); + let ty = instance.ty(self.tcx.tcx, self.typing_env()); mir::ConstAlloc { alloc_id, ty } } else { self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.param_env.and(gid)))? @@ -587,7 +579,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| { - let const_val = val.eval(*ecx.tcx, ecx.param_env, span).map_err(|err| { + let const_val = val.eval(*ecx.tcx, ecx.typing_env(), span).map_err(|err| { if M::ALL_CONSTS_ARE_PRECHECKED { match err { ErrorHandled::TooGeneric(..) => {}, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index d89d73824aa..fc6a1c4bbc5 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -40,6 +40,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( ) -> InterpResult<'tcx, ConstValue<'tcx>> { let tp_ty = args.type_at(0); let name = tcx.item_name(def_id); + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; interp_ok(match name { sym::type_name => { ensure_monomorphic_enough(tcx, tp_ty)?; @@ -48,11 +49,13 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( } sym::needs_drop => { ensure_monomorphic_enough(tcx, tp_ty)?; - ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)) + ConstValue::from_bool(tp_ty.needs_drop(tcx, typing_env)) } sym::pref_align_of => { // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. - let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(*e)))?; + let layout = tcx + .layout_of(typing_env.as_query_input(tp_ty)) + .map_err(|e| err_inval!(Layout(*e)))?; ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx) } sym::type_id => { @@ -355,7 +358,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let should_panic = !self .tcx - .check_validity_requirement((requirement, self.param_env.and(ty))) + .check_validity_requirement((requirement, self.typing_env().as_query_input(ty))) .map_err(|_| err_inval!(TooGeneric))?; if should_panic { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 09635c96e57..07566e9fda2 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -859,7 +859,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // # Global allocations if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) { - let (size, align) = global_alloc.size_and_align(*self.tcx, self.param_env); + let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env()); let mutbl = global_alloc.mutability(*self.tcx, self.param_env); let kind = match global_alloc { GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index a130ae89bcb..0157e6c2125 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -8,7 +8,7 @@ use rustc_abi as abi; use rustc_abi::{BackendRepr, HasDataLayout, Size}; use rustc_hir::def::Namespace; use rustc_middle::mir::interpret::ScalarSizeMismatch; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug, ty}; @@ -297,21 +297,25 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline] pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self { - let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(tcx.types.bool)).unwrap(); + let layout = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool)) + .unwrap(); Self::from_scalar(Scalar::from_bool(b), layout) } #[inline] pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self { let ty = tcx.ty_ordering_enum(None); - let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap(); + let layout = + tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap(); Self::from_scalar(Scalar::from_i8(c as i8), layout) } pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self { let layout = tcx .layout_of( - ty::ParamEnv::reveal_all().and(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])), + ty::TypingEnv::fully_monomorphized() + .as_query_input(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])), ) .unwrap(); Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout) @@ -341,7 +345,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline] #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980) - pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>)) -> (Self, Self) { + pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>)) -> (Self, Self) { let layout = self.layout; let (val0, val1) = self.to_scalar_pair(); ( @@ -773,8 +777,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { )?; if !mir_assign_valid_types( *self.tcx, - self.typing_mode(), - self.param_env, + self.typing_env(), self.layout_of(normalized_place_ty)?, op.layout, ) { @@ -833,9 +836,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }) }; let layout = - from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || { - self.layout_of(ty).into() - })?; + from_known_layout(self.tcx, self.typing_env(), layout, || self.layout_of(ty).into())?; let imm = match val_val { mir::ConstValue::Indirect { alloc_id, offset } => { // This is const data, no mutation allowed. diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index fbc85d37953..201f1b5dc62 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -533,7 +533,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } OffsetOf(fields) => { let val = - self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes(); + self.tcx.offset_of_subfield(self.typing_env(), layout, fields.iter()).bytes(); ImmTy::from_uint(val, usize_layout()) } UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index cc8d1db6cfb..13fcccca76b 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -540,8 +540,7 @@ where )?; if !mir_assign_valid_types( *self.tcx, - self.typing_mode(), - self.param_env, + self.typing_env(), self.layout_of(normalized_place_ty)?, place.layout, ) { @@ -871,13 +870,8 @@ where ) -> InterpResult<'tcx> { // We do NOT compare the types for equality, because well-typed code can // actually "transmute" `&mut T` to `&T` in an assignment without a cast. - let layout_compat = mir_assign_valid_types( - *self.tcx, - self.typing_mode(), - self.param_env, - src.layout(), - dest.layout(), - ); + let layout_compat = + mir_assign_valid_types(*self.tcx, self.typing_env(), src.layout(), dest.layout()); if !allow_transmute && !layout_compat { span_bug!( self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 50c0446b3cd..037c1a233ee 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -379,7 +379,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { for &const_ in body.required_consts() { let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?; - c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| { + c.eval(*self.tcx, self.typing_env(), const_.span).map_err(|err| { err.emit_note(*self.tcx); err })?; @@ -596,13 +596,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return interp_ok(layout); } - let layout = - from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || { - let local_ty = frame.body.local_decls[local].ty; - let local_ty = - self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; - self.layout_of(local_ty).into() - })?; + let layout = from_known_layout(self.tcx, self.typing_env(), layout, || { + let local_ty = frame.body.local_decls[local].ty; + let local_ty = + self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; + self.layout_of(local_ty).into() + })?; // Layouts of locals are requested a lot, so we cache them. state.layout.set(Some(layout)); diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 18cff2c5e0f..d4525243642 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -418,7 +418,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .collect::>>()?; let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx); - let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder); + let fn_sig = + self.tcx.normalize_erasing_late_bound_regions(self.typing_env(), fn_sig_binder); let extra_args = &args[fn_sig.inputs().len()..]; let extra_args = self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty)); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 3a68db9f7f7..005b430bc8a 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -448,7 +448,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { meta: MemPlaceMeta, pointee: TyAndLayout<'tcx>, ) -> InterpResult<'tcx> { - let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.param_env); + let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env()); match tail.kind() { ty::Dynamic(data, _, ty::Dyn) => { let vtable = meta.unwrap_meta().to_pointer(self.ecx)?; @@ -568,7 +568,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); }; let (size, _align) = - global_alloc.size_and_align(*self.ecx.tcx, self.ecx.param_env); + global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env()); if let GlobalAlloc::Static(did) = global_alloc { let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { @@ -955,7 +955,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ) -> Cow<'e, RangeSet> { assert!(layout.ty.is_union()); assert!(layout.is_sized(), "there are no unsized unions"); - let layout_cx = LayoutCx::new(*ecx.tcx, ecx.param_env); + let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env()); return M::cached_union_data_range(ecx, layout.ty, || { let mut out = RangeSet(Vec::new()); union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out); diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 0490195caf4..527236b2c22 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -47,7 +47,7 @@ pub fn provide(providers: &mut Providers) { providers.hooks.try_destructure_mir_constant_for_user_output = const_eval::try_destructure_mir_constant_for_user_output; providers.valtree_to_const_val = |tcx, (ty, valtree)| { - const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree) + const_eval::valtree_to_const_value(tcx, ty::ParamEnv::reveal_all().and(ty), valtree) }; providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| { util::check_validity_requirement(tcx, init_kind, param_env_and_ty) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 6fa7d369229..9507b24f603 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -9,7 +9,7 @@ use tracing::debug; pub fn is_disaligned<'tcx, L>( tcx: TyCtxt<'tcx>, local_decls: &L, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, place: Place<'tcx>, ) -> bool where @@ -22,8 +22,8 @@ where }; let ty = place.ty(local_decls, tcx).ty; - let unsized_tail = || tcx.struct_tail_for_codegen(ty, param_env); - match tcx.layout_of(param_env.and(ty)) { + let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env); + match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) if layout.align.abi <= pack && (layout.is_sized() diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index f743525f359..1afc910ce8f 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -3,7 +3,7 @@ use rustc_middle::bug; use rustc_middle::ty::layout::{ HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement, }; -use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; +use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt}; use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine}; use crate::interpret::{InterpCx, MemoryKind}; @@ -23,16 +23,16 @@ use crate::interpret::{InterpCx, MemoryKind}; pub fn check_validity_requirement<'tcx>( tcx: TyCtxt<'tcx>, kind: ValidityRequirement, - param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>, + input: PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> Result> { - let layout = tcx.layout_of(param_env_and_ty)?; + let layout = tcx.layout_of(input)?; // There is nothing strict or lax about inhabitedness. if kind == ValidityRequirement::Inhabited { return Ok(!layout.is_uninhabited()); } - let layout_cx = LayoutCx::new(tcx, param_env_and_ty.param_env); + let layout_cx = LayoutCx::new(tcx, input.typing_env); if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks { check_validity_requirement_strict(layout, &layout_cx, kind) } else { @@ -49,7 +49,7 @@ fn check_validity_requirement_strict<'tcx>( ) -> Result> { let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); - let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.param_env, machine); + let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env.param_env, machine); let allocated = cx .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap)) diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs index 0cf27d30c36..9eed1a20f15 100644 --- a/compiler/rustc_const_eval/src/util/compare_types.rs +++ b/compiler/rustc_const_eval/src/util/compare_types.rs @@ -5,18 +5,17 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, Variance}; +use rustc_middle::ty::{Ty, TyCtxt, TypingEnv, Variance}; use rustc_trait_selection::traits::ObligationCtxt; /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`. pub fn sub_types<'tcx>( tcx: TyCtxt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, src: Ty<'tcx>, dest: Ty<'tcx>, ) -> bool { - relate_types(tcx, typing_mode, param_env, Variance::Covariant, src, dest) + relate_types(tcx, typing_env, Variance::Covariant, src, dest) } /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`. @@ -26,8 +25,7 @@ pub fn sub_types<'tcx>( /// because we want to check for type equality. pub fn relate_types<'tcx>( tcx: TyCtxt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, variance: Variance, src: Ty<'tcx>, dest: Ty<'tcx>, @@ -36,8 +34,7 @@ pub fn relate_types<'tcx>( return true; } - let mut builder = tcx.infer_ctxt().ignoring_regions(); - let infcx = builder.build(typing_mode); + let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy(); let src = ocx.normalize(&cause, param_env, src); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 3080d8b3510..cf8c81c0b08 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -21,8 +21,7 @@ use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt}; use rustc_middle::ty::{ - AdtDef, GenericArgKind, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, + AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_session::lint::builtin::UNINHABITED_STATIC; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -114,15 +113,15 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b } } - let param_env = tcx.param_env(item_def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); for field in &def.non_enum_variant().fields { - let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args)) + let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args)) else { tcx.dcx().span_delayed_bug(span, "could not normalize field type"); continue; }; - if !allowed_union_field(field_ty, tcx, param_env) { + if !allowed_union_field(field_ty, tcx, typing_env.param_env) { let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { // We are currently checking the type this field came from, so it must be local. Some(Node::Field(field)) => (field.span, field.ty.span), @@ -137,7 +136,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b note: (), }); return false; - } else if field_ty.needs_drop(tcx, param_env) { + } else if field_ty.needs_drop(tcx, typing_env) { // This should never happen. But we can get here e.g. in case of name resolution errors. tcx.dcx() .span_delayed_bug(span, "we should never accept maybe-dropping union fields"); @@ -158,7 +157,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { // reason to allow any statics to be uninhabited. let ty = tcx.type_of(def_id).instantiate_identity(); let span = tcx.def_span(def_id); - let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) { + let layout = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { Ok(l) => l, // Foreign statics that overflow their allowed size should emit an error Err(LayoutError::SizeOverflow(_)) @@ -237,7 +236,10 @@ pub(super) fn check_opaque_for_cycles<'tcx>( // And also look for cycle errors in the layout of coroutines. if let Err(&LayoutError::Cycle(guar)) = - tcx.layout_of(tcx.param_env(def_id).and(Ty::new_opaque(tcx, def_id.to_def_id(), args))) + tcx.layout_of( + ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) + .as_query_input(Ty::new_opaque(tcx, def_id.to_def_id(), args)), + ) { return Err(guar); } @@ -1307,8 +1309,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) // "known" respecting #[non_exhaustive] attributes. let field_infos = adt.all_fields().map(|field| { let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did)); - let param_env = tcx.param_env(field.did); - let layout = tcx.layout_of(param_env.and(ty)); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, field.did); + let layout = tcx.layout_of(typing_env.as_query_input(ty)); // We are currently checking the type this field came from, so it must be local let span = tcx.hir().span_if_local(field.did).unwrap(); let trivial = layout.is_ok_and(|layout| layout.is_1zst()); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 1802f00bc1f..d8bf7fdbb0f 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1126,7 +1126,7 @@ fn check_type_defn<'tcx>( let ty = tcx.type_of(variant.tail().did).instantiate_identity(); let ty = tcx.erase_regions(ty); assert!(!ty.has_infer()); - ty.needs_drop(tcx, tcx.param_env(item.owner_id)) + ty.needs_drop(tcx, ty::TypingEnv::non_body_analysis(tcx, item.owner_id.def_id)) } }; // All fields (except for possibly the last) should be sized. @@ -1281,7 +1281,8 @@ fn check_item_type( UnsizedHandling::Forbid => true, UnsizedHandling::Allow => false, UnsizedHandling::AllowIfForeignTail => { - let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.param_env); + let tail = + tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env)); !matches!(tail.kind(), ty::Foreign(_)) } }; diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 5ff52376837..c2ad61820a7 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -259,7 +259,9 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() let ty_a = field.ty(tcx, args_a); let ty_b = field.ty(tcx, args_b); - if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) { + if let Ok(layout) = + tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a)) + { if layout.is_1zst() { // ignore 1-ZST fields return false; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 92f38a7dde0..39471931461 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -3,7 +3,7 @@ use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; use rustc_hir::{self as hir, HirId}; use rustc_middle::bug; use rustc_middle::ty::layout::LayoutError; -use rustc_middle::ty::{self, ParamEnv, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use crate::errors; @@ -130,7 +130,7 @@ fn is_valid_cmse_inputs<'tcx>( let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); for (index, ty) in fn_sig.inputs().iter().enumerate() { - let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?; + let layout = tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(*ty))?; let align = layout.layout.align().abi.bytes(); let size = layout.layout.size().bytes(); @@ -158,8 +158,10 @@ fn is_valid_cmse_output<'tcx>( // this type is only used for layout computation, which does not rely on regions let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let mut ret_ty = fn_sig.output(); - let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?; + let layout = tcx.layout_of(typing_env.as_query_input(ret_ty))?; let size = layout.layout.size().bytes(); if size <= 4 { @@ -182,7 +184,7 @@ fn is_valid_cmse_output<'tcx>( for variant_def in adt_def.variants() { for field_def in variant_def.fields.iter() { let ty = field_def.ty(tcx, args); - let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty))?; + let layout = tcx.layout_of(typing_env.as_query_input(ty))?; if !layout.layout.is_1zst() { ret_ty = ty; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 354993513da..1610848958e 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2357,8 +2357,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only assoc fns that return `Self` let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder(); let ret_ty = fn_sig.output(); - let ret_ty = - self.tcx.normalize_erasing_late_bound_regions(self.param_env, ret_ty); + let ret_ty = self.tcx.normalize_erasing_late_bound_regions( + self.typing_env(self.param_env), + ret_ty, + ); if !self.can_eq(self.param_env, ret_ty, adt_ty) { return None; } diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index a754f7fddc9..789530d35dd 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = tcx.hir().span(hir_id); let normalize = |ty| { let ty = self.resolve_vars_if_possible(ty); - self.tcx.normalize_erasing_regions(self.param_env, ty) + self.tcx.normalize_erasing_regions(self.typing_env(self.param_env), ty) }; let from = normalize(from); let to = normalize(to); @@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env); + let skel = |ty| SizeSkeleton::compute(ty, tcx, self.typing_env(self.param_env)); let sk_from = skel(from); let sk_to = skel(to); trace!(?sk_from, ?sk_to); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 175fca327f3..d50eff0deb0 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -1257,7 +1257,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option> { let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id)); - if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)) { + // FIXME(#132279): Using `non_body_analysis` here feels wrong. + if !ty.has_significant_drop( + self.tcx, + ty::TypingEnv::non_body_analysis(self.tcx, closure_def_id), + ) { debug!("does not have significant drop"); return None; } @@ -1535,8 +1539,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base_path_ty: Ty<'tcx>, captured_by_move_projs: Vec<&[Projection<'tcx>]>, ) -> bool { - let needs_drop = - |ty: Ty<'tcx>| ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)); + // FIXME(#132279): Using `non_body_analysis` here feels wrong. + let needs_drop = |ty: Ty<'tcx>| { + ty.has_significant_drop( + self.tcx, + ty::TypingEnv::non_body_analysis(self.tcx, closure_def_id), + ) + }; let is_drop_defined_for_ty = |ty: Ty<'tcx>| { let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span)); diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 391e640f8bc..8694800ac43 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -881,6 +881,8 @@ impl<'tcx> TypeFolder> for EagerlyNormalizeConsts<'tcx> { } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - self.tcx.try_normalize_erasing_regions(self.param_env, ct).unwrap_or(ct) + self.tcx + .try_normalize_erasing_regions(ty::TypingEnv::from_param_env(self.param_env), ct) + .unwrap_or(ct) } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 12df4a10e63..fc3b9863acc 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -38,7 +38,8 @@ use rustc_middle::ty::fold::{ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef, - GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, TypingMode, + GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt, TyVid, + TypeVisitable, TypingEnv, TypingMode, }; use rustc_span::Span; use rustc_span::symbol::Symbol; @@ -565,6 +566,13 @@ impl<'tcx> InferCtxtBuilder<'tcx> { (infcx, value, args) } + pub fn build_with_typing_env( + mut self, + TypingEnv { typing_mode, param_env }: TypingEnv<'tcx>, + ) -> (InferCtxt<'tcx>, ty::ParamEnv<'tcx>) { + (self.build(typing_mode), param_env) + } + pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> { let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } = *self; @@ -1278,6 +1286,42 @@ impl<'tcx> InferCtxt<'tcx> { u } + /// Extract [ty::TypingMode] of this inference context to get a `TypingEnv` + /// which contains the necessary information to use the trait system without + /// using canonicalization or carrying this inference context around. + pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> { + let typing_mode = match self.typing_mode(param_env) { + ty::TypingMode::Coherence => ty::TypingMode::Coherence, + // FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible + // to handle them without proper canonicalization. This means we may cause cycle + // errors and fail to reveal opaques while inside of bodies. We should rename this + // function and require explicit comments on all use-sites in the future. + ty::TypingMode::Analysis { defining_opaque_types: _ } => { + TypingMode::non_body_analysis() + } + ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis, + }; + ty::TypingEnv { typing_mode, param_env } + } + + /// Similar to [Self::canonicalize_query], except that it returns + /// a [PseudoCanonicalInput] and requires both the `value` and the + /// `param_env` to not contain any inference variables or placeholders. + pub fn pseudo_canonicalize_query( + &self, + param_env: ty::ParamEnv<'tcx>, + value: V, + ) -> PseudoCanonicalInput<'tcx, V> + where + V: TypeVisitable>, + { + debug_assert!(!value.has_infer()); + debug_assert!(!value.has_placeholders()); + debug_assert!(!param_env.has_infer()); + debug_assert!(!param_env.has_placeholders()); + self.typing_env(param_env).as_query_input(value) + } + /// The returned function is used in a fast path. If it returns `true` the variable is /// unchanged, `false` indicates that the status is unknown. #[inline] diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 130f3cb7c2a..f6366ec3b80 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2485,7 +2485,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { }); // Check if this ADT has a constrained layout (like `NonNull` and friends). - if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) { + if let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) { if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) = &layout.backend_repr { @@ -2521,7 +2521,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { ty: Ty<'tcx>, init: InitKind, ) -> Option { - let ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty); + let ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty); use rustc_type_ir::TyKind::*; match ty.kind() { @@ -2568,7 +2568,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { let definitely_inhabited = match variant .inhabited_predicate(cx.tcx, *adt_def) .instantiate(cx.tcx, args) - .apply_any_module(cx.tcx, cx.param_env) + .apply_any_module(cx.tcx, cx.typing_env()) { // Entirely skip uninhabited variants. Some(false) => return None, diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index aa7ec2659d0..6eec32beab0 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -19,7 +19,7 @@ use rustc_middle::bug; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths}; -use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode}; use rustc_session::lint::{ BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, }; @@ -708,6 +708,10 @@ impl<'tcx> LateContext<'tcx> { TypingMode::non_body_analysis() } + pub fn typing_env(&self) -> TypingEnv<'tcx> { + TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env } + } + /// Gets the type-checking results for the current body, /// or `None` if outside a body. pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> { @@ -906,7 +910,7 @@ impl<'tcx> LateContext<'tcx> { .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) .and_then(|assoc| { let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]); - tcx.try_normalize_erasing_regions(self.param_env, proj).ok() + tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok() }) } @@ -1010,10 +1014,10 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for LateContext<'tcx> { } } -impl<'tcx> ty::layout::HasParamEnv<'tcx> for LateContext<'tcx> { +impl<'tcx> ty::layout::HasTypingEnv<'tcx> for LateContext<'tcx> { #[inline] - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env() } } diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index cf68e41243f..dbc920ea5ae 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>( } let ty = args.type_at(0); - let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); + let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env()); let ocx = ObligationCtxt::new(&infcx); let body_def_id = cx.tcx.hir().body_owner_def_id(body_id); @@ -175,7 +175,7 @@ fn suggest_question_mark<'tcx>( ocx.register_bound( cause, - cx.param_env, + param_env, // Erase any region vids from the type, which may not be resolved infcx.tcx.erase_regions(ty), into_iterator_did, diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 394ea798d3e..45b188205d2 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -131,7 +131,7 @@ impl ClashingExternDeclarations { // Check that the declarations match. if !structurally_same_type( tcx, - tcx.param_env(this_fi.owner_id), + ty::TypingEnv::non_body_analysis(tcx, this_fi.owner_id), existing_decl_ty, this_decl_ty, types::CItemKind::Declaration, @@ -205,18 +205,18 @@ fn get_relevant_span(tcx: TyCtxt<'_>, fi: hir::OwnerId) -> Span { /// with the same members (as the declarations shouldn't clash). fn structurally_same_type<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>, ckind: types::CItemKind, ) -> bool { let mut seen_types = UnordSet::default(); - let result = structurally_same_type_impl(&mut seen_types, tcx, param_env, a, b, ckind); + let result = structurally_same_type_impl(&mut seen_types, tcx, typing_env, a, b, ckind); if cfg!(debug_assertions) && result { // Sanity-check: must have same ABI, size and alignment. // `extern` blocks cannot be generic, so we'll always get a layout here. - let a_layout = tcx.layout_of(param_env.and(a)).unwrap(); - let b_layout = tcx.layout_of(param_env.and(b)).unwrap(); + let a_layout = tcx.layout_of(typing_env.as_query_input(a)).unwrap(); + let b_layout = tcx.layout_of(typing_env.as_query_input(b)).unwrap(); assert_eq!(a_layout.backend_repr, b_layout.backend_repr); assert_eq!(a_layout.size, b_layout.size); assert_eq!(a_layout.align, b_layout.align); @@ -227,7 +227,7 @@ fn structurally_same_type<'tcx>( fn structurally_same_type_impl<'tcx>( seen_types: &mut UnordSet<(Ty<'tcx>, Ty<'tcx>)>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>, ckind: types::CItemKind, @@ -303,7 +303,7 @@ fn structurally_same_type_impl<'tcx>( structurally_same_type_impl( seen_types, tcx, - param_env, + typing_env, tcx.type_of(a_did).instantiate(tcx, a_gen_args), tcx.type_of(b_did).instantiate(tcx, b_gen_args), ckind, @@ -315,23 +315,23 @@ fn structurally_same_type_impl<'tcx>( // For arrays, we also check the length. a_len == b_len && structurally_same_type_impl( - seen_types, tcx, param_env, *a_ty, *b_ty, ckind, + seen_types, tcx, typing_env, *a_ty, *b_ty, ckind, ) } (Slice(a_ty), Slice(b_ty)) => { - structurally_same_type_impl(seen_types, tcx, param_env, *a_ty, *b_ty, ckind) + structurally_same_type_impl(seen_types, tcx, typing_env, *a_ty, *b_ty, ckind) } (RawPtr(a_ty, a_mutbl), RawPtr(b_ty, b_mutbl)) => { a_mutbl == b_mutbl && structurally_same_type_impl( - seen_types, tcx, param_env, *a_ty, *b_ty, ckind, + seen_types, tcx, typing_env, *a_ty, *b_ty, ckind, ) } (Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => { // For structural sameness, we don't need the region to be same. a_mut == b_mut && structurally_same_type_impl( - seen_types, tcx, param_env, *a_ty, *b_ty, ckind, + seen_types, tcx, typing_env, *a_ty, *b_ty, ckind, ) } (FnDef(..), FnDef(..)) => { @@ -346,12 +346,12 @@ fn structurally_same_type_impl<'tcx>( (a_sig.abi, a_sig.safety, a_sig.c_variadic) == (b_sig.abi, b_sig.safety, b_sig.c_variadic) && a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| { - structurally_same_type_impl(seen_types, tcx, param_env, *a, *b, ckind) + structurally_same_type_impl(seen_types, tcx, typing_env, *a, *b, ckind) }) && structurally_same_type_impl( seen_types, tcx, - param_env, + typing_env, a_sig.output(), b_sig.output(), ckind, @@ -379,14 +379,14 @@ fn structurally_same_type_impl<'tcx>( // An Adt and a primitive or pointer type. This can be FFI-safe if non-null // enum layout optimisation is being applied. (Adt(..), _) if is_primitive_or_pointer(b) => { - if let Some(a_inner) = types::repr_nullable_ptr(tcx, param_env, a, ckind) { + if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) { a_inner == b } else { false } } (_, Adt(..)) if is_primitive_or_pointer(a) => { - if let Some(b_inner) = types::repr_nullable_ptr(tcx, param_env, b, ckind) { + if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) { b_inner == a } else { false diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index afcfbebc14b..0e874669043 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -368,7 +368,7 @@ impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> { .cx .typeck_results() .expr_ty(expr) - .has_significant_drop(self.cx.tcx, self.cx.param_env) + .has_significant_drop(self.cx.tcx, self.cx.typing_env()) { return ControlFlow::Break(expr.span); } diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 2f338f42f19..38c38b59bc5 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -103,7 +103,8 @@ declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUE impl LateLintPass<'_> for QueryStability { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return }; - if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, args) { + if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args) + { let def_id = instance.def_id(); if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) { cx.emit_span_lint(POTENTIAL_QUERY_INSTABILITY, span, QueryInstability { @@ -544,7 +545,7 @@ impl Diagnostics { ) { // Is the callee marked with `#[rustc_lint_diagnostics]`? let Some(inst) = - ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args).ok().flatten() + ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, fn_gen_args).ok().flatten() else { return; }; diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index abee9ee7869..9e4e8333164 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { // If the type has a trivial Drop implementation, then it doesn't // matter that we drop the value immediately. - if !ty.needs_drop(cx.tcx, cx.param_env) { + if !ty.needs_drop(cx.tcx, cx.typing_env()) { return; } // Lint for patterns like `mutex.lock()`, which returns `Result` as well. diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index cf25ec99e67..36b1ff59c67 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -157,15 +157,17 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String), ); - let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); + let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env()); let suggest_display = is_str - || cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| { - infcx.type_implements_trait(t, [ty], cx.param_env).may_apply() - }); + || cx + .tcx + .get_diagnostic_item(sym::Display) + .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply()); let suggest_debug = !suggest_display - && cx.tcx.get_diagnostic_item(sym::Debug).is_some_and(|t| { - infcx.type_implements_trait(t, [ty], cx.param_env).may_apply() - }); + && cx + .tcx + .get_diagnostic_item(sym::Debug) + .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply()); let suggest_panic_any = !is_str && panic == sym::std_panic_macro; diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 4890a93fa76..76dc96ae00f 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -94,9 +94,9 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { let args = cx .tcx - .normalize_erasing_regions(cx.param_env, cx.typeck_results().node_args(expr.hir_id)); + .normalize_erasing_regions(cx.typing_env(), cx.typeck_results().node_args(expr.hir_id)); // Resolve the trait method instance. - let Ok(Some(i)) = ty::Instance::try_resolve(cx.tcx, cx.param_env, did, args) else { + let Ok(Some(i)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), did, args) else { return; }; // (Re)check that it implements the noop diagnostic. diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs index 89763059877..19763ce1ec5 100644 --- a/compiler/rustc_lint/src/tail_expr_drop_order.rs +++ b/compiler/rustc_lint/src/tail_expr_drop_order.rs @@ -103,7 +103,7 @@ impl TailExprDropOrder { if matches!(fn_kind, hir::intravisit::FnKind::Closure) { for &capture in cx.tcx.closure_captures(def_id) { if matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue) - && capture.place.ty().has_significant_drop(cx.tcx, cx.param_env) + && capture.place.ty().has_significant_drop(cx.tcx, cx.typing_env()) { locals.push(capture.var_ident.span); } @@ -113,7 +113,7 @@ impl TailExprDropOrder { if cx .typeck_results() .node_type(param.hir_id) - .has_significant_drop(cx.tcx, cx.param_env) + .has_significant_drop(cx.tcx, cx.typing_env()) { locals.push(param.span); } @@ -158,7 +158,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LocalCollector<'a, 'tcx> { fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) { if let PatKind::Binding(_binding_mode, id, ident, pat) = pat.kind { let ty = self.cx.typeck_results().node_type(id); - if ty.has_significant_drop(self.cx.tcx, self.cx.param_env) { + if ty.has_significant_drop(self.cx.tcx, self.cx.typing_env()) { self.locals.push(ident.span); } if let Some(pat) = pat { @@ -234,7 +234,10 @@ impl<'a, 'tcx> LintTailExpr<'a, 'tcx> { if Self::expr_eventually_point_into_local(expr) { return false; } - self.cx.typeck_results().expr_ty(expr).has_significant_drop(self.cx.tcx, self.cx.param_env) + self.cx + .typeck_results() + .expr_ty(expr) + .has_significant_drop(self.cx.tcx, self.cx.typing_env()) } } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index be70149b664..2e6cb993842 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -613,10 +613,11 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>( tcx: TyCtxt<'tcx>, variant: &'a ty::VariantDef, ) -> Option<&'a ty::FieldDef> { - let param_env = tcx.param_env(variant.def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, variant.def_id); variant.fields.iter().find(|field| { let field_ty = tcx.type_of(field.did).instantiate_identity(); - let is_1zst = tcx.layout_of(param_env.and(field_ty)).is_ok_and(|layout| layout.is_1zst()); + let is_1zst = + tcx.layout_of(typing_env.as_query_input(field_ty)).is_ok_and(|layout| layout.is_1zst()); !is_1zst }) } @@ -624,11 +625,11 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>( /// Is type known to be non-null? fn ty_is_known_nonnull<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, mode: CItemKind, ) -> bool { - let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty); + let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); match ty.kind() { ty::FnPtr(..) => true, @@ -649,7 +650,7 @@ fn ty_is_known_nonnull<'tcx>( def.variants() .iter() .filter_map(|variant| transparent_newtype_field(tcx, variant)) - .any(|field| ty_is_known_nonnull(tcx, param_env, field.ty(tcx, args), mode)) + .any(|field| ty_is_known_nonnull(tcx, typing_env, field.ty(tcx, args), mode)) } _ => false, } @@ -659,10 +660,10 @@ fn ty_is_known_nonnull<'tcx>( /// If the type passed in was not scalar, returns None. fn get_nullable_type<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ) -> Option> { - let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty); + let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); Some(match *ty.kind() { ty::Adt(field_def, field_args) => { @@ -679,7 +680,7 @@ fn get_nullable_type<'tcx>( .expect("No non-zst fields in transparent type.") .ty(tcx, field_args) }; - return get_nullable_type(tcx, param_env, inner_field_ty); + return get_nullable_type(tcx, typing_env, inner_field_ty); } ty::Int(ty) => Ty::new_int(tcx, ty), ty::Uint(ty) => Ty::new_uint(tcx, ty), @@ -708,10 +709,10 @@ fn get_nullable_type<'tcx>( /// - Does not have the `#[non_exhaustive]` attribute. fn is_niche_optimization_candidate<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ) -> bool { - if tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| !layout.is_1zst()) { + if tcx.layout_of(typing_env.as_query_input(ty)).is_ok_and(|layout| !layout.is_1zst()) { return false; } @@ -734,7 +735,7 @@ fn is_niche_optimization_candidate<'tcx>( /// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes. pub(crate) fn repr_nullable_ptr<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ckind: CItemKind, ) -> Option> { @@ -747,9 +748,9 @@ pub(crate) fn repr_nullable_ptr<'tcx>( let ty1 = field1.ty(tcx, args); let ty2 = field2.ty(tcx, args); - if is_niche_optimization_candidate(tcx, param_env, ty1) { + if is_niche_optimization_candidate(tcx, typing_env, ty1) { ty2 - } else if is_niche_optimization_candidate(tcx, param_env, ty2) { + } else if is_niche_optimization_candidate(tcx, typing_env, ty2) { ty1 } else { return None; @@ -760,20 +761,20 @@ pub(crate) fn repr_nullable_ptr<'tcx>( _ => return None, }; - if !ty_is_known_nonnull(tcx, param_env, field_ty, ckind) { + if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) { return None; } // At this point, the field's type is known to be nonnull and the parent enum is Option-like. // If the computed size for the field and the enum are different, the nonnull optimization isn't // being applied (and we've got a problem somewhere). - let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, param_env).ok(); + let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok(); if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) { bug!("improper_ctypes: Option nonnull optimization not applied?"); } // Return the nullable type this Option-like enum can be safely represented with. - let field_ty_layout = tcx.layout_of(param_env.and(field_ty)); + let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty)); if field_ty_layout.is_err() && !field_ty.has_non_region_param() { bug!("should be able to compute the layout of non-polymorphic type"); } @@ -784,10 +785,10 @@ pub(crate) fn repr_nullable_ptr<'tcx>( WrappingRange { start: 0, end } if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 => { - return Some(get_nullable_type(tcx, param_env, field_ty).unwrap()); + return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); } WrappingRange { start: 1, .. } => { - return Some(get_nullable_type(tcx, param_env, field_ty).unwrap()); + return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); } WrappingRange { start, end } => { unreachable!("Unhandled start and end range: ({}, {})", start, end) @@ -825,7 +826,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let field_ty = self .cx .tcx - .try_normalize_erasing_regions(self.cx.param_env, field_ty) + .try_normalize_erasing_regions(self.cx.typing_env(), field_ty) .unwrap_or(field_ty); self.check_type_for_ffi(acc, field_ty) } @@ -988,7 +989,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { { // Special-case types like `Option` and `Result` if let Some(ty) = - repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode) + repr_nullable_ptr(self.cx.tcx, self.cx.typing_env(), ty, self.mode) { return self.check_type_for_ffi(acc, ty); } @@ -1196,7 +1197,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let Some(ty) = self .cx .tcx - .try_normalize_erasing_regions(self.cx.param_env, ty) + .try_normalize_erasing_regions(self.cx.typing_env(), ty) .unwrap_or(ty) .visit_with(&mut ProhibitOpaqueTypes) .break_value() @@ -1220,7 +1221,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return; } - let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.param_env, ty).unwrap_or(ty); + let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.typing_env(), ty).unwrap_or(ty); // C doesn't really support passing arrays by value - the only way to pass an array by value // is through a struct. So, first test that the top level isn't an array, and then diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 6c13127b04e..5ec920d39f4 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -272,7 +272,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { || !ty.is_inhabited_from( cx.tcx, cx.tcx.parent_module(expr.hir_id).to_def_id(), - cx.param_env, + cx.typing_env(), ) { return Some(MustUsePath::Suppressed); @@ -556,7 +556,7 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements { if let hir::StmtKind::Semi(expr) = s.kind { if let hir::ExprKind::Path(_) = expr.kind { let ty = cx.typeck_results().expr_ty(expr); - if ty.needs_drop(cx.tcx, cx.param_env) { + if ty.needs_drop(cx.tcx, cx.typing_env()) { let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) { PathStatementDropSub::Suggestion { span: s.span, snippet } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 493db498b7c..ace46891f83 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -6,7 +6,7 @@ use rustc_ast::CRATE_NODE_ID; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; use rustc_middle::query::LocalCrate; -use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; +use rustc_middle::ty::{self, List, Ty, TyCtxt}; use rustc_session::Session; use rustc_session::config::CrateType; use rustc_session::cstore::{ @@ -613,7 +613,7 @@ impl<'tcx> Collector<'tcx> { .map(|ty| { let layout = self .tcx - .layout_of(ParamEnvAnd { param_env: ParamEnv::empty(), value: ty }) + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .expect("layout") .layout; // In both stdcall and fastcall, we always round up the argument size to the diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index f95635370dc..a51370369b8 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -102,10 +102,11 @@ impl<'tcx> ConstValue<'tcx> { pub fn try_to_bits_for_ty( &self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ) -> Option { - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + let size = + tcx.layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(ty)).ok()?.size; self.try_to_bits(size) } @@ -314,7 +315,7 @@ impl<'tcx> Const<'tcx> { pub fn eval( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, span: Span, ) -> Result, ErrorHandled> { match self { @@ -333,7 +334,7 @@ impl<'tcx> Const<'tcx> { } Const::Unevaluated(uneval, _) => { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` - tcx.const_eval_resolve(param_env, uneval, span) + tcx.const_eval_resolve(typing_env, uneval, span) } Const::Val(val, _) => Ok(val), } @@ -343,7 +344,7 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_scalar( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { if let Const::Ty(_, c) = self && let ty::ConstKind::Value(ty, val) = c.kind() @@ -354,7 +355,7 @@ impl<'tcx> Const<'tcx> { // pointer here, which valtrees don't represent.) Some(val.unwrap_leaf().into()) } else { - self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar() + self.eval(tcx, typing_env, DUMMY_SP).ok()?.try_to_scalar() } } @@ -362,23 +363,29 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_scalar_int( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { - self.try_eval_scalar(tcx, param_env)?.try_to_scalar_int().ok() + self.try_eval_scalar(tcx, typing_env)?.try_to_scalar_int().ok() } #[inline] - pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option { - let int = self.try_eval_scalar_int(tcx, param_env)?; - let size = - tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size; + pub fn try_eval_bits( + &self, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> Option { + let int = self.try_eval_scalar_int(tcx, typing_env)?; + let size = tcx + .layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(self.ty())) + .ok()? + .size; Some(int.to_bits(size)) } /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. #[inline] - pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 { - self.try_eval_bits(tcx, param_env) + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u128 { + self.try_eval_bits(tcx, typing_env) .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self)) } @@ -386,21 +393,21 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_target_usize( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { - Some(self.try_eval_scalar_int(tcx, param_env)?.to_target_usize(tcx)) + Some(self.try_eval_scalar_int(tcx, typing_env)?.to_target_usize(tcx)) } #[inline] /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. - pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u64 { - self.try_eval_target_usize(tcx, param_env) + pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u64 { + self.try_eval_target_usize(tcx, typing_env) .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } #[inline] - pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option { - self.try_eval_scalar_int(tcx, param_env)?.try_into().ok() + pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option { + self.try_eval_scalar_int(tcx, typing_env)?.try_into().ok() } #[inline] @@ -411,17 +418,16 @@ impl<'tcx> Const<'tcx> { pub fn from_bits( tcx: TyCtxt<'tcx>, bits: u128, - param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, ) -> Self { let size = tcx - .layout_of(param_env_ty) - .unwrap_or_else(|e| { - bug!("could not compute layout for {:?}: {:?}", param_env_ty.value, e) - }) + .layout_of(typing_env.as_query_input(ty)) + .unwrap_or_else(|e| bug!("could not compute layout for {ty:?}: {e:?}")) .size; let cv = ConstValue::Scalar(Scalar::from_uint(bits, size)); - Self::Val(cv, param_env_ty.value) + Self::Val(cv, ty) } #[inline] @@ -438,7 +444,8 @@ impl<'tcx> Const<'tcx> { pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { let ty = tcx.types.usize; - Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty)) + let typing_env = ty::TypingEnv::fully_monomorphized(); + Self::from_bits(tcx, n as u128, typing_env, ty) } #[inline] diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index f225ad94aa7..c4b0e6e39cc 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -351,7 +351,11 @@ impl<'tcx> GlobalAlloc<'tcx> { } } - pub fn size_and_align(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> (Size, Align) { + pub fn size_and_align( + &self, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> (Size, Align) { match self { GlobalAlloc::Static(def_id) => { let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { @@ -374,7 +378,7 @@ impl<'tcx> GlobalAlloc<'tcx> { .type_of(def_id) .no_bound_vars() .expect("statics should not have generic parameters"); - let layout = tcx.layout_of(param_env.and(ty)).unwrap(); + let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap(); assert!(layout.is_sized()); (layout.size, layout.align.abi) } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 2ecf1d0bcf8..7092f87a7d1 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -58,7 +58,7 @@ impl<'tcx> TyCtxt<'tcx> { #[instrument(level = "debug", skip(self))] pub fn const_eval_resolve( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ct: mir::UnevaluatedConst<'tcx>, span: Span, ) -> EvalToConstValueResult<'tcx> { @@ -72,14 +72,11 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - match ty::Instance::try_resolve( - self, param_env, - // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst? - ct.def, ct.args, - ) { + // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst? + match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; - self.const_eval_global_id(param_env, cid, span) + self.const_eval_global_id(typing_env.param_env, cid, span) } // For errors during resolution, we deliberately do not point at the usage site of the constant, // since for these errors the place the constant is used shouldn't matter. @@ -91,7 +88,7 @@ impl<'tcx> TyCtxt<'tcx> { #[instrument(level = "debug", skip(self))] pub fn const_eval_resolve_for_typeck( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ct: ty::UnevaluatedConst<'tcx>, span: Span, ) -> EvalToValTreeResult<'tcx> { @@ -105,10 +102,10 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - match ty::Instance::try_resolve(self, param_env, ct.def, ct.args) { + match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: None }; - self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| { + self.const_eval_global_id_for_typeck(typing_env.param_env, cid, span).inspect(|_| { // We are emitting the lint here instead of in `is_const_evaluatable` // as we normalize obligations before checking them, and normalization // uses this function to evaluate this constant. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 260c6543f98..425cb059e57 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -39,7 +39,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{ - self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingMode, + self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv, UserTypeAnnotationIndex, }; @@ -452,12 +452,17 @@ impl<'tcx> Body<'tcx> { self.basic_blocks.as_mut() } - pub fn typing_mode(&self, _tcx: TyCtxt<'tcx>) -> TypingMode<'tcx> { + pub fn typing_env(&self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> { match self.phase { - // FIXME(#132279): the MIR is quite clearly inside of a body, so we - // should instead reveal opaques defined by that body here. - MirPhase::Built | MirPhase::Analysis(_) => TypingMode::non_body_analysis(), - MirPhase::Runtime(_) => TypingMode::PostAnalysis, + // FIXME(#132279): we should reveal the opaques defined in the body during analysis. + MirPhase::Built | MirPhase::Analysis(_) => TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env: tcx.param_env(self.source.def_id()), + }, + MirPhase::Runtime(_) => TypingEnv { + typing_mode: ty::TypingMode::PostAnalysis, + param_env: tcx.param_env_reveal_all_normalized(self.source.def_id()), + }, } } @@ -618,7 +623,7 @@ impl<'tcx> Body<'tcx> { } /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the - /// dimscriminant in monomorphization, we return the discriminant bits and the + /// discriminant in monomorphization, we return the discriminant bits and the /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator. fn try_const_mono_switchint<'a>( tcx: TyCtxt<'tcx>, @@ -627,13 +632,15 @@ impl<'tcx> Body<'tcx> { ) -> Option<(u128, &'a SwitchTargets)> { // There are two places here we need to evaluate a constant. let eval_mono_const = |constant: &ConstOperand<'tcx>| { - let env = ty::ParamEnv::reveal_all(); + // FIXME(#132279): what is this, why are we using an empty environment with + // `RevealAll` here. + let typing_env = ty::TypingEnv::fully_monomorphized(); let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions( tcx, - env, + typing_env, crate::ty::EarlyBinder::bind(constant.const_), ); - mono_literal.try_eval_bits(tcx, env) + mono_literal.try_eval_bits(tcx, typing_env) }; let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else { diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 88ed90c3114..1ce735cec63 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -332,9 +332,9 @@ impl<'tcx> Operand<'tcx> { span: Span, ) -> Operand<'tcx> { debug_assert!({ - let param_env_and_ty = ty::ParamEnv::empty().and(ty); + let typing_env = ty::TypingEnv::fully_monomorphized(); let type_size = tcx - .layout_of(param_env_and_ty) + .layout_of(typing_env.as_query_input(ty)) .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}")) .size; let scalar_size = match val { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index f01ac305d3f..2083279e128 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -20,7 +20,7 @@ use smallvec::SmallVec; use super::{BasicBlock, Const, Local, UserTypeProjection}; use crate::mir::coverage::CoverageKind; use crate::ty::adjustment::PointerCoercion; -use crate::ty::{self, GenericArgsRef, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex}; +use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex}; /// Represents the "flavors" of MIR. /// @@ -100,13 +100,6 @@ impl MirPhase { MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized", } } - - pub fn param_env<'tcx>(&self, tcx: TyCtxt<'tcx>, body_def_id: DefId) -> ty::ParamEnv<'tcx> { - match self { - MirPhase::Built | MirPhase::Analysis(_) => tcx.param_env(body_def_id), - MirPhase::Runtime(_) => tcx.param_env_reveal_all_normalized(body_def_id), - } - } } /// See [`MirPhase::Analysis`]. diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index c5def5fc65b..9cb11cdd3b7 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -467,6 +467,18 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { } } +impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { + type Cache = DefaultCache; + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.value.default_span(tcx) + } + + fn ty_def_id(&self) -> Option { + self.value.ty_def_id() + } +} + impl Key for Symbol { type Cache = DefaultCache; @@ -575,7 +587,7 @@ impl Key for (LocalDefId, HirId) { } } -impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) { +impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) { type Cache = DefaultCache; // Just forward to `Ty<'tcx>` diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4068d06f6df..684d5b6c2a7 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -81,8 +81,8 @@ use crate::ty::layout::ValidityRequirement; use crate::ty::print::{PrintTraitRefExt, describe_as_module}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{ - self, CrateInherentImpls, GenericArg, GenericArgsRef, ParamEnvAnd, Ty, TyCtxt, TyCtxtFeed, - UnusedGenericParams, + self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt, + TyCtxtFeed, UnusedGenericParams, }; use crate::{dep_graph, mir, thir}; @@ -1341,10 +1341,10 @@ rustc_queries! { } query codegen_select_candidate( - key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) + key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>> ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { cache_on_disk_if { true } - desc { |tcx| "computing candidate for `{}`", key.1 } + desc { |tcx| "computing candidate for `{}`", key.value } } /// Return all `impl` blocks in the current crate. @@ -1406,15 +1406,15 @@ rustc_queries! { desc { "computing whether `{}` is `Unpin`", env.value } } /// Query backing `Ty::needs_drop`. - query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query needs_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } } /// Query backing `Ty::needs_async_drop`. - query needs_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query needs_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs async drop", env.value } } /// Query backing `Ty::has_significant_drop_raw`. - query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query has_significant_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` has a significant drop", env.value } } @@ -1451,7 +1451,7 @@ rustc_queries! { /// Computes the layout of a type. Note that this implicitly /// executes in "reveal all" mode, and will normalize the input type. query layout_of( - key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> + key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>> ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { depth_limit desc { "computing layout of `{}`", key.value } @@ -1464,7 +1464,7 @@ rustc_queries! { /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` /// instead, where the instance is an `InstanceKind::Virtual`. query fn_abi_of_fn_ptr( - key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> + key: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}` function pointers", key.value.0 } } @@ -1475,7 +1475,7 @@ rustc_queries! { /// NB: that includes virtual calls, which are represented by "direct calls" /// to an `InstanceKind::Virtual` instance (of `::fn`). query fn_abi_of_instance( - key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> + key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}`", key.value.0 } } @@ -2088,7 +2088,7 @@ rustc_queries! { /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. query try_normalize_generic_arg_after_erasing_regions( - goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> + goal: PseudoCanonicalInput<'tcx, GenericArg<'tcx>> ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } } @@ -2245,7 +2245,7 @@ rustc_queries! { /// from `Ok(None)` to avoid misleading diagnostics when an error /// has already been/will be emitted, for the original cause. query resolve_instance_raw( - key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)> + key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)> ) -> Result>, ErrorGuaranteed> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } } @@ -2283,7 +2283,7 @@ rustc_queries! { desc { "computing the backend features for CLI flags" } } - query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result> { + query check_validity_requirement(key: (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>)) -> Result> { desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 45ceb0a555d..8f26e05cb72 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -905,7 +905,7 @@ impl<'tcx> PatRange<'tcx> { &self, value: mir::Const<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { use Ordering::*; debug_assert_eq!(self.ty, value.ty()); @@ -913,10 +913,10 @@ impl<'tcx> PatRange<'tcx> { let value = PatRangeBoundary::Finite(value); // For performance, it's important to only do the second comparison if necessary. Some( - match self.lo.compare_with(value, ty, tcx, param_env)? { + match self.lo.compare_with(value, ty, tcx, typing_env)? { Less | Equal => true, Greater => false, - } && match value.compare_with(self.hi, ty, tcx, param_env)? { + } && match value.compare_with(self.hi, ty, tcx, typing_env)? { Less => true, Equal => self.end == RangeEnd::Included, Greater => false, @@ -929,17 +929,17 @@ impl<'tcx> PatRange<'tcx> { &self, other: &Self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { use Ordering::*; debug_assert_eq!(self.ty, other.ty); // For performance, it's important to only do the second comparison if necessary. Some( - match other.lo.compare_with(self.hi, self.ty, tcx, param_env)? { + match other.lo.compare_with(self.hi, self.ty, tcx, typing_env)? { Less => true, Equal => self.end == RangeEnd::Included, Greater => false, - } && match self.lo.compare_with(other.hi, self.ty, tcx, param_env)? { + } && match self.lo.compare_with(other.hi, self.ty, tcx, typing_env)? { Less => true, Equal => other.end == RangeEnd::Included, Greater => false, @@ -985,9 +985,14 @@ impl<'tcx> PatRangeBoundary<'tcx> { Self::NegInfinity | Self::PosInfinity => None, } } - pub fn eval_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 { + pub fn eval_bits( + self, + ty: Ty<'tcx>, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> u128 { match self { - Self::Finite(value) => value.eval_bits(tcx, param_env), + Self::Finite(value) => value.eval_bits(tcx, typing_env), Self::NegInfinity => { // Unwrap is ok because the type is known to be numeric. ty.numeric_min_and_max_as_bits(tcx).unwrap().0 @@ -999,13 +1004,13 @@ impl<'tcx> PatRangeBoundary<'tcx> { } } - #[instrument(skip(tcx, param_env), level = "debug", ret)] + #[instrument(skip(tcx, typing_env), level = "debug", ret)] pub fn compare_with( self, other: Self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { use PatRangeBoundary::*; match (self, other) { @@ -1034,8 +1039,8 @@ impl<'tcx> PatRangeBoundary<'tcx> { _ => {} } - let a = self.eval_bits(ty, tcx, param_env); - let b = other.eval_bits(ty, tcx, param_env); + let a = self.eval_bits(ty, tcx, typing_env); + let b = other.eval_bits(ty, tcx, typing_env); match ty.kind() { ty::Float(ty::FloatTy::F16) => { diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 0773eb7a3be..79d56702be2 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -498,12 +498,13 @@ impl<'tcx> AdtDef<'tcx> { expr_did: DefId, ) -> Result, ErrorGuaranteed> { assert!(self.is_enum()); - let param_env = tcx.param_env(expr_did); + let repr_type = self.repr().discr_type(); match tcx.const_eval_poly(expr_did) { Ok(val) => { + let typing_env = ty::TypingEnv::post_analysis(tcx, expr_did); let ty = repr_type.to_ty(tcx); - if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) { + if let Some(b) = val.try_to_bits_for_ty(tcx, typing_env, ty) { trace!("discriminants: {} ({:?})", b, repr_type); Ok(Discr { val: b, ty }) } else { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 5689f3d4265..3bd09fc91c6 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -9,7 +9,7 @@ use tracing::{debug, instrument}; use crate::middle::resolve_bound_vars as rbv; use crate::mir::interpret::{LitToConstInput, Scalar}; -use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt}; mod int; mod kind; @@ -330,17 +330,22 @@ impl<'tcx> Const<'tcx> { None } - #[inline] /// Creates a constant with the given integer value and interns it. - pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self { + #[inline] + pub fn from_bits( + tcx: TyCtxt<'tcx>, + bits: u128, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, + ) -> Self { let size = tcx - .layout_of(ty) + .layout_of(typing_env.as_query_input(ty)) .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}")) .size; ty::Const::new_value( tcx, ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()), - ty.value, + ty, ) } @@ -353,13 +358,13 @@ impl<'tcx> Const<'tcx> { #[inline] /// Creates an interned bool constant. pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self { - Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) + Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool) } #[inline] /// Creates an interned usize constant. pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { - Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) + Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize) } /// Panics if self.kind != ty::ConstKind::Value @@ -393,15 +398,15 @@ impl<'tcx> Const<'tcx> { self.try_to_valtree()?.0.try_to_target_usize(tcx) } - #[inline] /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it /// contains const generic parameters or pointers). - pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { + #[inline] + pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option { let (scalar, ty) = self.try_to_scalar()?; let scalar = scalar.try_to_scalar_int().ok()?; - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; - // if `ty` does not depend on generic parameters, use an empty param_env + let input = typing_env.with_reveal_all_normalized(tcx).as_query_input(ty); + let size = tcx.layout_of(input).ok()?.size; Some(scalar.to_bits(size)) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 84ac281c258..2ba1bf2822f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -596,8 +596,16 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.coroutine_is_async_gen(coroutine_def_id) } - fn layout_is_pointer_like(self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { - self.layout_of(self.erase_regions(param_env.and(ty))) + // We don't use `TypingEnv` here as it's only defined in `rustc_middle` and + // `rustc_next_trait_solver` shouldn't have to know about it. + fn layout_is_pointer_like( + self, + typing_mode: ty::TypingMode<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + let typing_env = ty::TypingEnv { typing_mode, param_env }; + self.layout_of(self.erase_regions(typing_env).as_query_input(self.erase_regions(ty))) .is_ok_and(|layout| layout.layout.is_pointer_like(&self.data_layout)) } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index bf741f63a3d..505c7278176 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -3,7 +3,7 @@ use smallvec::SmallVec; use tracing::instrument; use crate::ty::context::TyCtxt; -use crate::ty::{self, DefId, OpaqueTypeKey, ParamEnv, Ty}; +use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TypingEnv}; /// Represents whether some type is inhabited in a given context. /// Examples of uninhabited types are `!`, `enum Void {}`, or a struct @@ -35,8 +35,13 @@ pub enum InhabitedPredicate<'tcx> { impl<'tcx> InhabitedPredicate<'tcx> { /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module. - pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool { - self.apply_revealing_opaque(tcx, param_env, module_def_id, &|_| None) + pub fn apply( + self, + tcx: TyCtxt<'tcx>, + typing_env: TypingEnv<'tcx>, + module_def_id: DefId, + ) -> bool { + self.apply_revealing_opaque(tcx, typing_env, module_def_id, &|_| None) } /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module, @@ -44,13 +49,13 @@ impl<'tcx> InhabitedPredicate<'tcx> { pub fn apply_revealing_opaque( self, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, module_def_id: DefId, reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option>, ) -> bool { let Ok(result) = self.apply_inner::( tcx, - param_env, + typing_env, &mut Default::default(), &|id| Ok(tcx.is_descendant_of(module_def_id, id)), reveal_opaque, @@ -59,25 +64,25 @@ impl<'tcx> InhabitedPredicate<'tcx> { } /// Same as `apply`, but returns `None` if self contains a module predicate - pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(()), &|_| None).ok() + pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> Option { + self.apply_inner(tcx, typing_env, &mut Default::default(), &|_| Err(()), &|_| None).ok() } /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is, /// privately uninhabited types are considered always uninhabited. - pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool { + pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> bool { let Ok(result) = - self.apply_inner::(tcx, param_env, &mut Default::default(), &|_| Ok(true), &|_| { + self.apply_inner::(tcx, typing_env, &mut Default::default(), &|_| Ok(true), &|_| { None }); result } - #[instrument(level = "debug", skip(tcx, param_env, in_module, reveal_opaque), ret)] + #[instrument(level = "debug", skip(tcx, typing_env, in_module, reveal_opaque), ret)] fn apply_inner( self, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection in_module: &impl Fn(DefId) -> Result, reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option>, @@ -94,7 +99,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { // we have a param_env available, we can do better. Self::GenericType(t) => { let normalized_pred = tcx - .try_normalize_erasing_regions(param_env, t) + .try_normalize_erasing_regions(typing_env, t) .map_or(self, |t| t.inhabited_predicate(tcx)); match normalized_pred { // We don't have more information than we started with, so consider inhabited. @@ -107,7 +112,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { } eval_stack.push(t); let ret = - pred.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque); + pred.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque); eval_stack.pop(); ret } @@ -126,7 +131,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { eval_stack.push(t); let ret = t.inhabited_predicate(tcx).apply_inner( tcx, - param_env, + typing_env, eval_stack, in_module, reveal_opaque, @@ -136,10 +141,10 @@ impl<'tcx> InhabitedPredicate<'tcx> { } }, Self::And([a, b]) => try_and(a, b, |x| { - x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque) + x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque) }), Self::Or([a, b]) => try_or(a, b, |x| { - x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque) + x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque) }), } } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index dd00db8635f..4a5f6d80f24 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -181,18 +181,18 @@ impl<'tcx> Ty<'tcx> { self, tcx: TyCtxt<'tcx>, module: DefId, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { - self.inhabited_predicate(tcx).apply(tcx, param_env, module) + self.inhabited_predicate(tcx).apply(tcx, typing_env, module) } /// Returns true if the type is uninhabited without regard to visibility pub fn is_privately_uninhabited( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { - !self.inhabited_predicate(tcx).apply_ignore_module(tcx, param_env) + !self.inhabited_predicate(tcx).apply_ignore_module(tcx, typing_env) } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 0d1c56f0d38..d42b6be4787 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -178,9 +178,9 @@ pub enum InstanceKind<'tcx> { impl<'tcx> Instance<'tcx> { /// Returns the `Ty` corresponding to this `Instance`, with generic instantiations applied and /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. - pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { + pub fn ty(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); - tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty) + tcx.instantiate_and_normalize_erasing_regions(self.args, typing_env, ty) } /// Finds a crate that contains a monomorphization of this instance that @@ -519,7 +519,7 @@ impl<'tcx> Instance<'tcx> { #[instrument(level = "debug", skip(tcx), ret)] pub fn try_resolve( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, ) -> Result>, ErrorGuaranteed> { @@ -537,17 +537,14 @@ impl<'tcx> Instance<'tcx> { // All regions in the result of this query are erased, so it's // fine to erase all of the input regions. - - // HACK(eddyb) erase regions in `args` first, so that `param_env.and(...)` - // below is more likely to ignore the bounds in scope (e.g. if the only - // generic parameters mentioned by `args` were lifetime ones). + let typing_env = tcx.erase_regions(typing_env); let args = tcx.erase_regions(args); - tcx.resolve_instance_raw(tcx.erase_regions(param_env.and((def_id, args)))) + tcx.resolve_instance_raw(typing_env.as_query_input((def_id, args))) } pub fn expect_resolve( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, span: Span, @@ -558,7 +555,7 @@ impl<'tcx> Instance<'tcx> { let span_or_local_def_span = || if span.is_dummy() && def_id.is_local() { tcx.def_span(def_id) } else { span }; - match ty::Instance::try_resolve(tcx, param_env, def_id, args) { + match ty::Instance::try_resolve(tcx, typing_env, def_id, args) { Ok(Some(instance)) => instance, Ok(None) => { let type_length = type_length(args); @@ -600,7 +597,7 @@ impl<'tcx> Instance<'tcx> { pub fn resolve_for_fn_ptr( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, ) -> Option> { @@ -608,7 +605,7 @@ impl<'tcx> Instance<'tcx> { // Use either `resolve_closure` or `resolve_for_vtable` assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}"); let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr); - Instance::try_resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { + Instance::try_resolve(tcx, typing_env, def_id, args).ok().flatten().map(|mut resolved| { match resolved.def { InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => { debug!(" => fn pointer created for function with #[track_caller]"); @@ -648,7 +645,7 @@ impl<'tcx> Instance<'tcx> { pub fn expect_resolve_for_vtable( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, span: Span, @@ -664,7 +661,7 @@ impl<'tcx> Instance<'tcx> { return Instance { def: InstanceKind::VTableShim(def_id), args }; } - let mut resolved = Instance::expect_resolve(tcx, param_env, def_id, args, span); + let mut resolved = Instance::expect_resolve(tcx, typing_env, def_id, args, span); let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable); match resolved.def { @@ -743,7 +740,7 @@ impl<'tcx> Instance<'tcx> { let args = tcx.mk_args(&[ty.into()]); Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP), @@ -755,7 +752,7 @@ impl<'tcx> Instance<'tcx> { let args = tcx.mk_args(&[ty.into()]); Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP), @@ -883,16 +880,16 @@ impl<'tcx> Instance<'tcx> { pub fn instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, v: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable>, { if let Some(args) = self.args_for_mir_body() { - tcx.instantiate_and_normalize_erasing_regions(args, param_env, v) + tcx.instantiate_and_normalize_erasing_regions(args, typing_env, v) } else { - tcx.normalize_erasing_regions(param_env, v.instantiate_identity()) + tcx.normalize_erasing_regions(typing_env, v.instantiate_identity()) } } @@ -901,21 +898,21 @@ impl<'tcx> Instance<'tcx> { pub fn try_instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, v: EarlyBinder<'tcx, T>, ) -> Result> where T: TypeFoldable>, { if let Some(args) = self.args_for_mir_body() { - tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v) + tcx.try_instantiate_and_normalize_erasing_regions(args, typing_env, v) } else { // We're using `instantiate_identity` as e.g. // `FnPtrShim` is separately generated for every // instantiation of the `FnDef`, so the MIR body // is already instantiated. Any generic parameters it // contains are generic parameters from the caller. - tcx.try_normalize_erasing_regions(param_env, v.instantiate_identity()) + tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity()) } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index a0eb9029319..8625a8dcb2a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -297,12 +297,12 @@ impl<'tcx> IntoDiagArg for LayoutError<'tcx> { #[derive(Clone, Copy)] pub struct LayoutCx<'tcx> { pub calc: abi::LayoutCalculator>, - pub param_env: ty::ParamEnv<'tcx>, + pub typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> LayoutCx<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - Self { calc: abi::LayoutCalculator::new(tcx), param_env } + pub fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self { + Self { calc: abi::LayoutCalculator::new(tcx), typing_env } } } @@ -337,12 +337,12 @@ impl<'tcx> SizeSkeleton<'tcx> { pub fn compute( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { debug_assert!(!ty.has_non_region_infer()); // First try computing a static layout. - let err = match tcx.layout_of(param_env.and(ty)) { + let err = match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) => { if layout.is_sized() { return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi))); @@ -367,7 +367,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let tail = tcx.struct_tail_raw( pointee, - |ty| match tcx.try_normalize_erasing_regions(param_env, ty) { + |ty| match tcx.try_normalize_erasing_regions(typing_env, ty) { Ok(ty) => ty, Err(e) => Ty::new_error_with_message( tcx, @@ -402,7 +402,7 @@ impl<'tcx> SizeSkeleton<'tcx> { return Ok(SizeSkeleton::Known(Size::from_bytes(0), None)); } - match SizeSkeleton::compute(inner, tcx, param_env)? { + match SizeSkeleton::compute(inner, tcx, typing_env)? { // This may succeed because the multiplication of two types may overflow // but a single size of a nested array will not. SizeSkeleton::Known(s, a) => { @@ -432,7 +432,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let i = VariantIdx::from_usize(i); let fields = def.variant(i).fields.iter().map(|field| { - SizeSkeleton::compute(field.ty(tcx, args), tcx, param_env) + SizeSkeleton::compute(field.ty(tcx, args), tcx, typing_env) }); let mut ptr = None; for field in fields { @@ -491,11 +491,11 @@ impl<'tcx> SizeSkeleton<'tcx> { } ty::Alias(..) => { - let normalized = tcx.normalize_erasing_regions(param_env, ty); + let normalized = tcx.normalize_erasing_regions(typing_env, ty); if ty == normalized { Err(err) } else { - SizeSkeleton::compute(normalized, tcx, param_env) + SizeSkeleton::compute(normalized, tcx, typing_env) } } @@ -521,8 +521,14 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout { fn tcx(&self) -> TyCtxt<'tcx>; } -pub trait HasParamEnv<'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx>; +pub trait HasTypingEnv<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx>; + + /// FIXME(#132279): This method should not be used as in the future + /// everything should take a `TypingEnv` instead. Remove it as that point. + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.typing_env().param_env + } } impl<'tcx> HasDataLayout for TyCtxt<'tcx> { @@ -577,9 +583,9 @@ impl<'tcx> HasTyCtxt<'tcx> for TyCtxtAt<'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for LayoutCx<'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env +impl<'tcx> HasTypingEnv<'tcx> for LayoutCx<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env } } @@ -646,7 +652,7 @@ pub type TyAndLayout<'tcx> = rustc_abi::TyAndLayout<'tcx, Ty<'tcx>>; /// Trait for contexts that want to be able to compute layouts of types. /// This automatically gives access to `LayoutOf`, through a blanket `impl`. -pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> { +pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasTypingEnv<'tcx> { /// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be /// returned from `layout_of` (see also `handle_layout_err`). type LayoutOfResult: MaybeResult> = TyAndLayout<'tcx>; @@ -692,7 +698,7 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { let tcx = self.tcx().at(span); MaybeResult::from( - tcx.layout_of(self.param_env().and(ty)) + tcx.layout_of(self.typing_env().as_query_input(ty)) .map_err(|err| self.handle_layout_err(*err, span, ty)), ) } @@ -716,7 +722,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx> { impl<'tcx, C> TyAbiInterface<'tcx, C> for Ty<'tcx> where - C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>, + C: HasTyCtxt<'tcx> + HasTypingEnv<'tcx>, { fn ty_and_layout_for_variant( this: TyAndLayout<'tcx>, @@ -736,10 +742,10 @@ where Variants::Single { index } => { let tcx = cx.tcx(); - let param_env = cx.param_env(); + let typing_env = cx.typing_env(); // Deny calling for_variant more than once for non-Single enums. - if let Ok(original_layout) = tcx.layout_of(param_env.and(this.ty)) { + if let Ok(original_layout) = tcx.layout_of(typing_env.as_query_input(this.ty)) { assert_eq!(original_layout.variants, Variants::Single { index }); } @@ -780,7 +786,7 @@ where fn field_ty_or_layout<'tcx>( this: TyAndLayout<'tcx>, - cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), + cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>), i: usize, ) -> TyMaybeWithLayout<'tcx> { let tcx = cx.tcx(); @@ -823,12 +829,13 @@ where Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil) }; - // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing - // the `Result` should always work because the type is - // always either `*mut ()` or `&'static mut ()`. + // NOTE: using an fully monomorphized typing env and `unwrap`-ing + // the `Result` should always work because the type is always either + // `*mut ()` or `&'static mut ()`. + let typing_env = ty::TypingEnv::fully_monomorphized(); return TyMaybeWithLayout::TyAndLayout(TyAndLayout { ty: this.ty, - ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap() + ..tcx.layout_of(typing_env.as_query_input(unit_ptr_ty)).unwrap() }); } @@ -848,7 +855,7 @@ where && !pointee.references_error() { let metadata = tcx.normalize_erasing_regions( - cx.param_env(), + cx.typing_env(), Ty::new_projection(tcx, metadata_def_id, [pointee]), ); @@ -865,7 +872,7 @@ where metadata } } else { - match tcx.struct_tail_for_codegen(pointee, cx.param_env()).kind() { + match tcx.struct_tail_for_codegen(pointee, cx.typing_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()), _ => bug!("TyAndLayout::field({:?}): not applicable", this), @@ -953,7 +960,7 @@ where match field_ty_or_layout(this, cx, i) { TyMaybeWithLayout::Ty(field_ty) => { - cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| { + cx.tcx().layout_of(cx.typing_env().as_query_input(field_ty)).unwrap_or_else(|e| { bug!( "failed to get layout for `{field_ty}`: {e:?},\n\ despite it being a field (#{i}) of an existing layout: {this:#?}", @@ -972,18 +979,18 @@ where offset: Size, ) -> Option { let tcx = cx.tcx(); - let param_env = cx.param_env(); + let typing_env = cx.typing_env(); let pointee_info = match *this.ty.kind() { ty::RawPtr(p_ty, _) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(p_ty)).ok().map(|layout| PointeeInfo { + tcx.layout_of(typing_env.as_query_input(p_ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: None, }) } ty::FnPtr(..) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(this.ty)).ok().map(|layout| PointeeInfo { + tcx.layout_of(typing_env.as_query_input(this.ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: None, @@ -996,14 +1003,14 @@ where let optimize = tcx.sess.opts.optimize != OptLevel::No; let kind = match mt { hir::Mutability::Not => PointerKind::SharedRef { - frozen: optimize && ty.is_freeze(tcx, cx.param_env()), + frozen: optimize && ty.is_freeze(tcx, typing_env.param_env), }, hir::Mutability::Mut => PointerKind::MutableRef { - unpin: optimize && ty.is_unpin(tcx, cx.param_env()), + unpin: optimize && ty.is_unpin(tcx, typing_env.param_env), }, }; - tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo { + tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: Some(kind), @@ -1093,7 +1100,7 @@ where debug_assert!(pointee.safe.is_none()); let optimize = tcx.sess.opts.optimize != OptLevel::No; pointee.safe = Some(PointerKind::Box { - unpin: optimize && boxed_ty.is_unpin(tcx, cx.param_env()), + unpin: optimize && boxed_ty.is_unpin(tcx, typing_env.param_env), global: this.ty.is_box_global(tcx), }); } @@ -1304,9 +1311,11 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { let span = self.layout_tcx_at_span(); let tcx = self.tcx().at(span); - MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err( - |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), - )) + MaybeResult::from( + tcx.fn_abi_of_fn_ptr(self.typing_env().as_query_input((sig, extra_args))).map_err( + |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), + ), + ) } /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for @@ -1326,17 +1335,19 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { let tcx = self.tcx().at(span); MaybeResult::from( - tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| { - // HACK(eddyb) at least for definitions of/calls to `Instance`s, - // we can get some kind of span even if one wasn't provided. - // However, we don't do this early in order to avoid calling - // `def_span` unconditionally (which may have a perf penalty). - let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; - self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance { - instance, - extra_args, - }) - }), + tcx.fn_abi_of_instance(self.typing_env().as_query_input((instance, extra_args))) + .map_err(|err| { + // HACK(eddyb) at least for definitions of/calls to `Instance`s, + // we can get some kind of span even if one wasn't provided. + // However, we don't do this early in order to avoid calling + // `def_span` unconditionally (which may have a perf penalty). + let span = + if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; + self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance { + instance, + extra_args, + }) + }), ) } } @@ -1346,14 +1357,14 @@ impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {} impl<'tcx> TyCtxt<'tcx> { pub fn offset_of_subfield( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, mut layout: TyAndLayout<'tcx>, indices: I, ) -> Size where I: Iterator, { - let cx = LayoutCx::new(self, param_env); + let cx = LayoutCx::new(self, typing_env); let mut offset = Size::ZERO; for (variant, field) in indices { @@ -1363,7 +1374,7 @@ impl<'tcx> TyCtxt<'tcx> { layout = layout.field(&cx, index); if !layout.is_sized() { // If it is not sized, then the tail must still have at least a known static alignment. - let tail = self.struct_tail_for_codegen(layout.ty, param_env); + let tail = self.struct_tail_for_codegen(layout.ty, typing_env); if !matches!(tail.kind(), ty::Slice(..)) { bug!( "offset of not-statically-aligned field (type {:?}) cannot be computed statically", diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7fda0662a34..d6f7ee748bb 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -103,7 +103,7 @@ use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::ModChild; use crate::middle::privacy::EffectiveVisibilities; use crate::mir::{Body, CoroutineLayout}; -use crate::query::Providers; +use crate::query::{IntoQueryParam, Providers}; use crate::traits::{self, Reveal}; use crate::ty; pub use crate::ty::diagnostics::*; @@ -1122,6 +1122,104 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> { } } +/// The environment in which to do trait solving. +/// +/// Most of the time you only need to care about the `ParamEnv` +/// as the `TypingMode` is simply stored in the `InferCtxt`. +/// +/// However, there are some places which rely on trait solving +/// without using an `InferCtxt` themselves. For these to be +/// able to use the trait system they have to be able to initialize +/// such an `InferCtxt` with the right `typing_mode`, so they need +/// to track both. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(TypeVisitable, TypeFoldable)] +pub struct TypingEnv<'tcx> { + pub typing_mode: TypingMode<'tcx>, + pub param_env: ParamEnv<'tcx>, +} + +impl<'tcx> TypingEnv<'tcx> { + // FIXME(#132279): This method should be removed but simplifies the + // transition. + pub fn from_param_env(param_env: ParamEnv<'tcx>) -> TypingEnv<'tcx> { + TypingEnv { typing_mode: TypingMode::from_param_env(param_env), param_env } + } + + /// Create a typing environment with no where-clauses in scope + /// where all opaque types and default associated items are revealed. + /// + /// This is only suitable for monomorphized, post-typeck environments. + /// Do not use this for MIR optimizations, as even though they also + /// use `TypingMode::PostAnalysis`, they may still have where-clauses + /// in scope. + pub fn fully_monomorphized() -> TypingEnv<'tcx> { + TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env: ParamEnv::reveal_all() } + } + + /// Create a typing environment for use during analysis outside of a body. + /// + /// Using a typing environment inside of bodies is not supported as the body + /// may define opaque types. In this case the used functions have to be + /// converted to use proper canonical inputs instead. + pub fn non_body_analysis( + tcx: TyCtxt<'tcx>, + def_id: impl IntoQueryParam, + ) -> TypingEnv<'tcx> { + TypingEnv { typing_mode: TypingMode::non_body_analysis(), param_env: tcx.param_env(def_id) } + } + + pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam) -> TypingEnv<'tcx> { + TypingEnv { + typing_mode: TypingMode::PostAnalysis, + param_env: tcx.param_env_reveal_all_normalized(def_id), + } + } + + /// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all + /// opaque types in the `param_env`. + pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> { + let TypingEnv { typing_mode: _, param_env } = self; + let param_env = param_env.with_reveal_all_normalized(tcx); + TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env } + } + + /// Combine this typing environment with the given `value` to be used by + /// not (yet) canonicalized queries. This only works if the value does not + /// contain anything local to some `InferCtxt`, i.e. inference variables or + /// placeholders. + pub fn as_query_input(self, value: T) -> PseudoCanonicalInput<'tcx, T> + where + T: TypeVisitable>, + { + debug_assert!(!value.has_infer()); + // FIXME(#132279): We should assert that the value does not contain any placeholders + // as these placeholders are also local to the current inference context. However, we + // currently use pseudo-canonical queries in the trait solver which replaces params with + // placeholders. We should also simply not use pseudo-canonical queries in the trait + // solver, at which point we can readd this assert. + // + // debug_assert!(!value.has_placeholders()); + PseudoCanonicalInput { typing_env: self, value } + } +} + +/// Similar to `CanonicalInput`, this carries the `typing_mode` and the environment +/// necessary to do any kind of trait solving inside of nested queries. +/// +/// Unlike proper canonicalization, this requires the `param_env` and the `value` to not +/// contain anything local to the `infcx` of the caller, so we don't actually canonicalize +/// anything. +/// +/// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)` +/// or by using `typing_env.as_query_input(value)`. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(HashStable)] +pub struct PseudoCanonicalInput<'tcx, T> { + pub typing_env: TypingEnv<'tcx>, + pub value: T, +} + #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] pub struct Destructor { /// The `DefId` of the destructor method diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index e51d2201922..f611b69905c 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -35,16 +35,16 @@ impl<'tcx> TyCtxt<'tcx> { /// /// This should only be used outside of type inference. For example, /// it assumes that normalization will succeed. - #[tracing::instrument(level = "debug", skip(self, param_env), ret)] - pub fn normalize_erasing_regions(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T + #[tracing::instrument(level = "debug", skip(self, typing_env), ret)] + pub fn normalize_erasing_regions(self, typing_env: ty::TypingEnv<'tcx>, value: T) -> T where T: TypeFoldable>, { debug!( - "normalize_erasing_regions::<{}>(value={:?}, param_env={:?})", + "normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})", std::any::type_name::(), value, - param_env, + typing_env, ); // Erase first before we do the real query -- this keeps the @@ -55,7 +55,7 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_aliases() { value } else { - value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env }) + value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, typing_env }) } } @@ -66,17 +66,17 @@ impl<'tcx> TyCtxt<'tcx> { /// succeeds. pub fn try_normalize_erasing_regions( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: T, ) -> Result> where T: TypeFoldable>, { debug!( - "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})", + "try_normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})", std::any::type_name::(), value, - param_env, + typing_env, ); // Erase first before we do the real query -- this keeps the @@ -87,7 +87,7 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_aliases() { Ok(value) } else { - let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env); + let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, typing_env); value.try_fold_with(&mut folder) } } @@ -103,17 +103,17 @@ impl<'tcx> TyCtxt<'tcx> { // FIXME(@lcnr): This method should not be necessary, we now normalize // inside of binders. We should be able to only use // `tcx.instantiate_bound_regions_with_erased`. - #[tracing::instrument(level = "debug", skip(self, param_env))] + #[tracing::instrument(level = "debug", skip(self, typing_env))] pub fn normalize_erasing_late_bound_regions( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: ty::Binder<'tcx, T>, ) -> T where T: TypeFoldable>, { let value = self.instantiate_bound_regions_with_erased(value); - self.normalize_erasing_regions(param_env, value) + self.normalize_erasing_regions(typing_env, value) } /// Monomorphizes a type from the AST by first applying the @@ -125,14 +125,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable>, { let instantiated = value.instantiate(self, param_args); - self.normalize_erasing_regions(param_env, instantiated) + self.normalize_erasing_regions(typing_env, instantiated) } /// Monomorphizes a type from the AST by first applying the @@ -143,20 +143,20 @@ impl<'tcx> TyCtxt<'tcx> { pub fn try_instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: EarlyBinder<'tcx, T>, ) -> Result> where T: TypeFoldable>, { let instantiated = value.instantiate(self, param_args); - self.try_normalize_erasing_regions(param_env, instantiated) + self.try_normalize_erasing_regions(typing_env, instantiated) } } struct NormalizeAfterErasingRegionsFolder<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { @@ -164,8 +164,7 @@ impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { &self, arg: ty::GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { - let arg = self.param_env.and(arg); - + let arg = self.typing_env.as_query_input(arg); self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!( "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead", arg.value @@ -189,12 +188,12 @@ impl<'tcx> TypeFolder> for NormalizeAfterErasingRegionsFolder<'tcx> struct TryNormalizeAfterErasingRegionsFolder<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { - fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - TryNormalizeAfterErasingRegionsFolder { tcx, param_env } + fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self { + TryNormalizeAfterErasingRegionsFolder { tcx, typing_env } } #[instrument(skip(self), level = "debug")] @@ -202,10 +201,8 @@ impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { &self, arg: ty::GenericArg<'tcx>, ) -> Result, NoSolution> { - let arg = self.param_env.and(arg); - debug!(?arg); - - self.tcx.try_normalize_generic_arg_after_erasing_regions(arg) + let input = self.typing_env.as_query_input(arg); + self.tcx.try_normalize_generic_arg_after_erasing_regions(input) } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 3c6e34160f4..1108619828d 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -18,6 +18,7 @@ use rustc_span::sym; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; +use super::TypingEnv; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::Providers; use crate::ty::layout::{FloatExt, IntegerExt}; @@ -177,9 +178,13 @@ impl<'tcx> TyCtxt<'tcx> { /// Should only be called if `ty` has no inference variables and does not /// need its lifetimes preserved (e.g. as part of codegen); otherwise /// normalization attempt may cause compiler bugs. - pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { + pub fn struct_tail_for_codegen( + self, + ty: Ty<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> Ty<'tcx> { let tcx = self; - tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {}) + tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(typing_env, ty), || {}) } /// Returns the deeply last field of nested structures, or the same type if @@ -271,11 +276,11 @@ impl<'tcx> TyCtxt<'tcx> { self, source: Ty<'tcx>, target: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>) { let tcx = self; tcx.struct_lockstep_tails_raw(source, target, |ty| { - tcx.normalize_erasing_regions(param_env, ty) + tcx.normalize_erasing_regions(typing_env, ty) }) } @@ -420,10 +425,10 @@ impl<'tcx> TyCtxt<'tcx> { // Async drop glue morphology is an internal detail, so reveal_all probably // should be fine - let param_env = ty::ParamEnv::reveal_all(); - if ty.needs_async_drop(self, param_env) { + let typing_env = ty::TypingEnv::fully_monomorphized(); + if ty.needs_async_drop(self, typing_env) { AsyncDropGlueMorphology::Custom - } else if ty.needs_drop(self, param_env) { + } else if ty.needs_drop(self, typing_env) { AsyncDropGlueMorphology::DeferredDropInPlace } else { AsyncDropGlueMorphology::Noop @@ -683,12 +688,10 @@ impl<'tcx> TyCtxt<'tcx> { } /// Get the type of the pointer to the static that we use in MIR. - pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> { + pub fn static_ptr_ty(self, def_id: DefId, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> { // Make sure that any constants in the static's type are evaluated. - let static_ty = self.normalize_erasing_regions( - ty::ParamEnv::empty(), - self.type_of(def_id).instantiate_identity(), - ); + let static_ty = + self.normalize_erasing_regions(typing_env, self.type_of(def_id).instantiate_identity()); // Make sure that accesses to unsafe statics end up using raw pointers. // For thread-locals, this needs to be kept in sync with `Rvalue::ty`. @@ -1157,15 +1160,17 @@ impl<'tcx> Ty<'tcx> { /// Returns the maximum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option> { + let typing_env = TypingEnv::fully_monomorphized(); self.numeric_min_and_max_as_bits(tcx) - .map(|(_, max)| ty::Const::from_bits(tcx, max, ty::ParamEnv::empty().and(self))) + .map(|(_, max)| ty::Const::from_bits(tcx, max, typing_env, self)) } /// Returns the minimum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option> { + let typing_env = TypingEnv::fully_monomorphized(); self.numeric_min_and_max_as_bits(tcx) - .map(|(min, _)| ty::Const::from_bits(tcx, min, ty::ParamEnv::empty().and(self))) + .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self)) } /// Checks whether values of this type `T` are *moved* or *copied* @@ -1345,7 +1350,7 @@ impl<'tcx> Ty<'tcx> { /// /// Note that this method is used to check eligible types in unions. #[inline] - pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn needs_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1359,14 +1364,13 @@ impl<'tcx> Ty<'tcx> { }; // This doesn't depend on regions, so try to minimize distinct - // query keys used. - // If normalization fails, we just use `query_ty`. - debug_assert!(!param_env.has_infer()); + // query keys used. If normalization fails, we just use `query_ty`. + debug_assert!(!typing_env.param_env.has_infer()); let query_ty = tcx - .try_normalize_erasing_regions(param_env, query_ty) + .try_normalize_erasing_regions(typing_env, query_ty) .unwrap_or_else(|_| tcx.erase_regions(query_ty)); - tcx.needs_drop_raw(param_env.and(query_ty)) + tcx.needs_drop_raw(typing_env.as_query_input(query_ty)) } } } @@ -1385,7 +1389,7 @@ impl<'tcx> Ty<'tcx> { // FIXME(zetanumbers): Note that this method is used to check eligible types // in unions. #[inline] - pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1401,12 +1405,12 @@ impl<'tcx> Ty<'tcx> { // This doesn't depend on regions, so try to minimize distinct // query keys used. // If normalization fails, we just use `query_ty`. - debug_assert!(!param_env.has_infer()); + debug_assert!(!typing_env.has_infer()); let query_ty = tcx - .try_normalize_erasing_regions(param_env, query_ty) + .try_normalize_erasing_regions(typing_env, query_ty) .unwrap_or_else(|_| tcx.erase_regions(query_ty)); - tcx.needs_async_drop_raw(param_env.and(query_ty)) + tcx.needs_async_drop_raw(typing_env.as_query_input(query_ty)) } } } @@ -1420,7 +1424,7 @@ impl<'tcx> Ty<'tcx> { /// Note that this method is used to check for change in drop order for /// 2229 drop reorder migration analysis. #[inline] - pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1443,8 +1447,8 @@ impl<'tcx> Ty<'tcx> { // This doesn't depend on regions, so try to minimize distinct // query keys used. - let erased = tcx.normalize_erasing_regions(param_env, query_ty); - tcx.has_significant_drop_raw(param_env.and(erased)) + let erased = tcx.normalize_erasing_regions(typing_env, query_ty); + tcx.has_significant_drop_raw(typing_env.as_query_input(erased)) } } } diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 963fa12a8c7..e5eeb23be25 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -97,7 +97,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( assert!(vtable_entries.len() >= vtable_min_entries(tcx, poly_trait_ref)); let layout = tcx - .layout_of(ty::ParamEnv::reveal_all().and(ty)) + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .expect("failed to build vtable representation"); assert!(layout.is_sized(), "can't create a vtable for an unsized type"); let size = layout.size.bytes(); @@ -117,7 +117,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( let idx: u64 = u64::try_from(idx).unwrap(); let scalar = match entry { VtblEntry::MetadataDropInPlace => { - if ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) { + if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) { let instance = ty::Instance::resolve_drop_in_place(tcx, ty); let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT); let fn_ptr = Pointer::from(fn_alloc_id); diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs index ed27a880562..acfb78b3f6e 100644 --- a/compiler/rustc_middle/src/util/call_kind.rs +++ b/compiler/rustc_middle/src/util/call_kind.rs @@ -8,7 +8,7 @@ use rustc_span::symbol::Ident; use rustc_span::{DesugaringKind, Span, sym}; use tracing::debug; -use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, ParamEnv, Ty, TyCtxt}; +use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum CallDesugaringKind { @@ -62,7 +62,7 @@ pub enum CallKind<'tcx> { pub fn call_kind<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, method_did: DefId, method_args: GenericArgsRef<'tcx>, fn_call_span: Span, @@ -98,10 +98,10 @@ pub fn call_kind<'tcx>( Some(CallKind::Operator { self_arg, trait_id, self_ty: method_args.type_at(0) }) } else if is_deref { let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| { - Instance::try_resolve(tcx, param_env, deref_target, method_args).transpose() + Instance::try_resolve(tcx, typing_env, deref_target, method_args).transpose() }); if let Some(Ok(instance)) = deref_target { - let deref_target_ty = instance.ty(tcx, param_env); + let deref_target_ty = instance.ty(tcx, typing_env); Some(CallKind::DerefCoercion { deref_target: tcx.def_span(instance.def_id()), deref_target_ty, diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 4815db47b16..e809c9a23f3 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -25,7 +25,7 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::thir::*; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; mod parse; @@ -77,7 +77,7 @@ pub(super) fn build_custom_mir<'tcx>( let mut pctxt = ParseCtxt { tcx, - param_env: tcx.param_env(did), + typing_env: body.typing_env(tcx), thir, source_scope: OUTERMOST_SOURCE_SCOPE, body: &mut body, @@ -136,7 +136,7 @@ fn parse_attribute(attr: &Attribute) -> MirPhase { struct ParseCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, thir: &'a Thir<'tcx>, source_scope: SourceScope, body: &'a mut Body<'tcx>, diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 07964e304b9..d08809ef67b 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -151,7 +151,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { expected: "constant pattern".to_string(), }); }; - values.push(value.eval_bits(self.tcx, self.param_env)); + values.push(value.eval_bits(self.tcx, self.typing_env)); targets.push(self.parse_block(arm.body)?); } @@ -385,7 +385,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { | ExprKind::NonHirLiteral { .. } | ExprKind::ConstBlock { .. } => Ok({ let value = as_constant_inner(expr, |_| None, self.tcx); - value.const_.eval_bits(self.tcx, self.param_env) + value.const_.eval_bits(self.tcx, self.typing_env) }), ) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 3f2e3b956fc..640408cb9c8 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -114,8 +114,7 @@ fn lit_to_mir_constant<'tcx>( ) -> Result, LitToConstError> { let LitToConstInput { lit, ty, neg } = lit_input; let trunc = |n| { - let param_ty = ty::ParamEnv::reveal_all().and(ty); - let width = match tcx.layout_of(param_ty) { + let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { Ok(layout) => layout.size, Err(_) => { tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit)) diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 112eac32264..aad7d54833b 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -123,7 +123,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match category { Category::Constant if matches!(needs_temporary, NeedsTemporary::No) - || !expr.ty.needs_drop(this.tcx, this.param_env) => + || !expr.ty.needs_drop(this.tcx, this.typing_env()) => { let constant = this.as_constant(expr); block.and(Operand::Constant(Box::new(constant))) diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 1985dd3fca0..4a859e869e7 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -197,7 +197,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { { let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx); let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not)); - let layout = this.tcx.layout_of(this.param_env.and(source_expr.ty)); + let layout = + this.tcx.layout_of(this.typing_env().as_query_input(source_expr.ty)); let discr = this.temp(discr_ty, source_expr.span); this.cfg.push_assign( block, @@ -229,7 +230,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let range_val = Const::from_bits( this.tcx, range, - ty::ParamEnv::empty().and(unsigned_ty), + ty::TypingEnv::fully_monomorphized(), + unsigned_ty, ); let lit_op = this.literal_operand(expr.span, range_val); let is_bin_op = this.temp(bool_ty, expr_span); @@ -812,9 +814,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Helper to get a `-1` value of the appropriate type fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let param_ty = ty::ParamEnv::empty().and(ty); - let size = self.tcx.layout_of(param_ty).unwrap().size; - let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let size = self.tcx.layout_of(typing_env.as_query_input(ty)).unwrap().size; + let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), typing_env, ty); self.literal_operand(span, literal) } @@ -822,10 +824,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Helper to get the minimum value of the appropriate type fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { assert!(ty.is_signed()); - let param_ty = ty::ParamEnv::empty().and(ty); - let bits = self.tcx.layout_of(param_ty).unwrap().size.bits(); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let bits = self.tcx.layout_of(typing_env.as_query_input(ty)).unwrap().size.bits(); let n = 1 << (bits - 1); - let literal = Const::from_bits(self.tcx, n, param_ty); + let literal = Const::from_bits(self.tcx, n, typing_env, ty); self.literal_operand(span, literal) } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index dc317feb20c..0dec56d21ae 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -266,7 +266,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // that makes the call. target: expr .ty - .is_inhabited_from(this.tcx, this.parent_module, this.param_env) + .is_inhabited_from( + this.tcx, + this.parent_module, + this.infcx.typing_env(this.param_env), + ) .then_some(success), call_source: if from_hir_call { CallSource::Normal diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index 76034c03b4b..02ca12028d3 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Generate better code for things that don't need to be // dropped. - if lhs_expr.ty.needs_drop(this.tcx, this.param_env) { + if lhs_expr.ty.needs_drop(this.tcx, this.typing_env()) { let rhs = unpack!(block = this.as_local_rvalue(block, rhs)); let lhs = unpack!(block = this.as_place(block, lhs)); block = diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs index 6df50057ee8..fcbf84a41d9 100644 --- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs @@ -214,7 +214,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> { || !v .inhabited_predicate(cx.tcx, adt_def) .instantiate(cx.tcx, args) - .apply_ignore_module(cx.tcx, cx.param_env) + .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env)) }) && (adt_def.did().is_local() || !adt_def.is_variant_list_non_exhaustive()); if irrefutable { diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 37cedd8cf5c..4f7bbc4ce3e 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -567,7 +567,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // not to add such values here. let is_covering_range = |test_case: &TestCase<'_, 'tcx>| { test_case.as_range().is_some_and(|range| { - matches!(range.contains(value, self.tcx, self.param_env), None | Some(true)) + matches!( + range.contains(value, self.tcx, self.typing_env()), + None | Some(true) + ) }) }; let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| { @@ -584,7 +587,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None } else { fully_matched = true; - let bits = value.eval_bits(self.tcx, self.param_env); + let bits = value.eval_bits(self.tcx, self.typing_env()); Some(TestBranch::Constant(value, bits)) } } @@ -596,7 +599,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fully_matched = false; let not_contained = sorted_candidates.keys().filter_map(|br| br.as_constant()).copied().all( - |val| matches!(range.contains(val, self.tcx, self.param_env), Some(false)), + |val| { + matches!(range.contains(val, self.tcx, self.typing_env()), Some(false)) + }, ); not_contained.then(|| { @@ -608,7 +613,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { (TestKind::If, TestCase::Constant { value }) => { fully_matched = true; - let value = value.try_eval_bool(self.tcx, self.param_env).unwrap_or_else(|| { + let value = value.try_eval_bool(self.tcx, self.typing_env()).unwrap_or_else(|| { span_bug!(test.span, "expected boolean value but got {value:?}") }); Some(if value { TestBranch::Success } else { TestBranch::Failure }) @@ -688,7 +693,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fully_matched = false; // If the testing range does not overlap with pattern range, // the pattern can be matched only if this test fails. - if !test.overlaps(pat, self.tcx, self.param_env)? { + if !test.overlaps(pat, self.tcx, self.typing_env())? { Some(TestBranch::Failure) } else { None @@ -697,7 +702,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } (TestKind::Range(range), &TestCase::Constant { value }) => { fully_matched = false; - if !range.contains(value, self.tcx, self.param_env)? { + if !range.contains(value, self.tcx, self.typing_env())? { // `value` is not contained in the testing range, // so `value` can be matched only if this test fails. Some(TestBranch::Failure) diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index 53cb99d44e8..a14dcad6573 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -32,7 +32,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns a zero literal operand for the appropriate type, works for /// bool, char and integers. pub(crate) fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let literal = Const::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty)); + let literal = Const::from_bits(self.tcx, 0, ty::TypingEnv::fully_monomorphized(), ty); self.literal_operand(span, literal) } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 46be2aee637..cf8dc597b7b 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -230,6 +230,10 @@ struct Capture<'tcx> { } impl<'a, 'tcx> Builder<'a, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.infcx.typing_env(self.param_env) + } + fn is_bound_var_in_guard(&self, id: LocalVarId) -> bool { self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id)) } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index a7e56b8f589..e63fbeeac66 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -1010,7 +1010,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { let needs_drop = match drop_kind { DropKind::Value => { - if !self.local_decls[local].ty.needs_drop(self.tcx, self.param_env) { + if !self.local_decls[local].ty.needs_drop(self.tcx, self.typing_env()) { return; } true diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 33e194fa246..da6b52ce0b8 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -566,7 +566,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { && adt_def.is_union() { if let Some(assigned_ty) = self.assignment_info { - if assigned_ty.needs_drop(self.tcx, self.param_env) { + if assigned_ty + .needs_drop(self.tcx, ty::TypingEnv::from_param_env(self.param_env)) + { // This would be unsafe, but should be outright impossible since we // reject such unions. assert!( diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 00f65e0c7d0..62c6d85b73f 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -528,7 +528,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo } if let ty::Ref(_, sub_ty, _) = self.ty.kind() { - if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) { + if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.typing_env()) { diag.note(fluent::mir_build_reference_note); } } diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index cb9a4e2604e..a1b75c22c4d 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -136,12 +136,17 @@ impl<'tcx> TerminatorClassifier<'tcx> for CallRecursion<'tcx> { let func_ty = func.ty(body, tcx); if let ty::FnDef(callee, args) = *func_ty.kind() { - let Ok(normalized_args) = tcx.try_normalize_erasing_regions(param_env, args) else { + let Ok(normalized_args) = + tcx.try_normalize_erasing_regions(ty::TypingEnv::from_param_env(param_env), args) + else { return false; }; - let (callee, call_args) = if let Ok(Some(instance)) = - Instance::try_resolve(tcx, param_env, callee, normalized_args) - { + let (callee, call_args) = if let Ok(Some(instance)) = Instance::try_resolve( + tcx, + ty::TypingEnv::from_param_env(param_env), + callee, + normalized_args, + ) { (instance.def_id(), instance.args) } else { (callee, normalized_args) diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index b8877a64e47..3fa0e4def82 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -2,7 +2,7 @@ use rustc_ast as ast; use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; -use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt}; +use rustc_middle::ty::{self, ScalarInt, TyCtxt}; use tracing::trace; use crate::build::parse_float_into_scalar; @@ -14,8 +14,7 @@ pub(crate) fn lit_to_const<'tcx>( let LitToConstInput { lit, ty, neg } = lit_input; let trunc = |n| { - let param_ty = ParamEnv::reveal_all().and(ty); - let width = match tcx.layout_of(param_ty) { + let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { Ok(layout) => layout.size, Err(_) => { tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit)) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 64457031997..198fa4ffb7a 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -284,10 +284,9 @@ impl<'tcx> Cx<'tcx> { let ty = adt_def.repr().discr_type(); let discr_ty = ty.to_ty(tcx); - let param_env_ty = self.param_env.and(discr_ty); let size = tcx - .layout_of(param_env_ty) - .unwrap_or_else(|e| panic!("could not compute layout for {param_env_ty:?}: {e:?}")) + .layout_of(self.typing_env().as_query_input(discr_ty)) + .unwrap_or_else(|e| panic!("could not compute layout for {discr_ty:?}: {e:?}")) .size; let (lit, overflowing) = ScalarInt::truncate_from_uint(discr_offset as u128, size); @@ -1025,7 +1024,7 @@ impl<'tcx> Cx<'tcx> { // but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics Res::Def(DefKind::Static { .. }, id) => { // this is &raw for extern static or static mut, and & for other statics - let ty = self.tcx.static_ptr_ty(id); + let ty = self.tcx.static_ptr_ty(id, self.typing_env()); let temp_lifetime = self .rvalue_scopes .temporary_scope(self.region_scope_tree, expr.hir_id.local_id); diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 377931e3be7..dfc180f5261 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -12,6 +12,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::bug; use rustc_middle::middle::region; use rustc_middle::thir::*; +use rustc_middle::ty::solve::Reveal; use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; use tracing::instrument; @@ -109,6 +110,17 @@ impl<'tcx> Cx<'tcx> { } } + fn typing_mode(&self) -> ty::TypingMode<'tcx> { + debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing); + // FIXME(#132279): In case we're in a body, we should use a typing + // mode which reveals the opaque types defined by that body. + ty::TypingMode::non_body_analysis() + } + + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env } + } + #[instrument(level = "debug", skip(self))] fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box> { pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index f222a869c03..73fcbeaef82 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -721,8 +721,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { .variant(*variant_index) .inhabited_predicate(self.tcx, *adt) .instantiate(self.tcx, args); - variant_inhabited.apply(self.tcx, cx.param_env, cx.module) - && !variant_inhabited.apply_ignore_module(self.tcx, cx.param_env) + variant_inhabited.apply(self.tcx, cx.typing_env(), cx.module) + && !variant_inhabited.apply_ignore_module(self.tcx, cx.typing_env()) } else { false }; @@ -1124,7 +1124,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( } if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() { - if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.param_env) { + if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.typing_env()) { err.note("references are always considered inhabited"); } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 82632350af5..6b462198db6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -50,10 +50,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { struct ConstToPat<'tcx> { span: Span, - param_env: ty::ParamEnv<'tcx>, // inference context used for checking `T: Structural` bounds. infcx: InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, treat_byte_string_as_slice: bool, } @@ -81,6 +81,10 @@ impl<'tcx> ConstToPat<'tcx> { self.infcx.tcx } + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.infcx.typing_env(self.param_env) + } + fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool { ty.is_structural_eq_shallow(self.infcx.tcx) } @@ -100,13 +104,14 @@ impl<'tcx> ConstToPat<'tcx> { // // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All` // instead of having this logic here - let param_env = - self.tcx().erase_regions(self.param_env).with_reveal_all_normalized(self.tcx()); + let typing_env = + self.tcx().erase_regions(self.typing_env()).with_reveal_all_normalized(self.tcx()); let uv = self.tcx().erase_regions(uv); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(param_env, uv, self.span) { + let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span) + { Ok(Ok(c)) => c, Err(ErrorHandled::Reported(_, _)) => { // Let's tell the use where this failing const occurs. @@ -187,7 +192,7 @@ impl<'tcx> ConstToPat<'tcx> { .map(|(idx, (val, ty))| { let field = FieldIdx::new(idx); // Patterns can only use monomorphic types. - let ty = self.tcx().normalize_erasing_regions(self.param_env, ty); + let ty = self.tcx().normalize_erasing_regions(self.typing_env(), ty); FieldPat { field, pattern: self.valtree_to_pat(val, ty) } }) .collect() diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index ec852add94d..d17bc8566cc 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -242,7 +242,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity); let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity); - let cmp = lo.compare_with(hi, ty, self.tcx, self.param_env); + let cmp = lo.compare_with(hi, ty, self.tcx, ty::TypingEnv::from_param_env(self.param_env)); let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty })); match (end, cmp) { // `x..y` where `x < y`. diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 9a1f000d39d..494b7d54d8a 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -6,7 +6,6 @@ use rustc_index::Idx; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::span_bug; -use rustc_middle::traits::Reveal; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt}; use rustc_span::DUMMY_SP; @@ -111,7 +110,7 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug { fn patch(&mut self) -> &mut MirPatch<'tcx>; fn body(&self) -> &'a Body<'tcx>; fn tcx(&self) -> TyCtxt<'tcx>; - fn param_env(&self) -> ty::ParamEnv<'tcx>; + fn typing_env(&self) -> ty::TypingEnv<'tcx>; // Drop logic @@ -273,9 +272,9 @@ where let subpath = self.elaborator.field_subpath(variant_path, field); let tcx = self.tcx(); - assert_eq!(self.elaborator.param_env().reveal(), Reveal::All); + assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis); let field_ty = - tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, args)); + tcx.normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args)); (tcx.mk_place_field(base_place, field, field_ty), subpath) }) @@ -372,7 +371,7 @@ where let mut fields = fields; fields.retain(|&(place, _)| { - self.place_ty(place).needs_drop(self.tcx(), self.elaborator.param_env()) + self.place_ty(place).needs_drop(self.tcx(), self.elaborator.typing_env()) }); debug!("drop_ladder - fields needing drop: {:?}", fields); @@ -544,11 +543,11 @@ where } else { have_otherwise = true; - let param_env = self.elaborator.param_env(); + let typing_env = self.elaborator.typing_env(); let have_field_with_drop_glue = variant .fields .iter() - .any(|field| field.ty(tcx, args).needs_drop(tcx, param_env)); + .any(|field| field.ty(tcx, args).needs_drop(tcx, typing_env)); if have_field_with_drop_glue { have_otherwise_with_drop_glue = true; } diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index af2d514fc76..ed8678de1eb 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -462,7 +462,7 @@ impl<'tcx> Map<'tcx> { drop(assignments); // Create values for places whose type have scalar layout. - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); for place_info in self.places.iter_mut() { // The user requires a bound on the number of created values. if let Some(value_limit) = value_limit @@ -471,13 +471,13 @@ impl<'tcx> Map<'tcx> { break; } - if let Ok(ty) = tcx.try_normalize_erasing_regions(param_env, place_info.ty) { + if let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, place_info.ty) { place_info.ty = ty; } // Allocate a value slot if it doesn't have one, and the user requested one. assert!(place_info.value_index.is_none()); - if let Ok(layout) = tcx.layout_of(param_env.and(place_info.ty)) + if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(place_info.ty)) && layout.backend_repr.is_scalar() { place_info.value_index = Some(self.value_count.into()); @@ -874,7 +874,7 @@ impl TryFrom> for TrackElem { pub fn iter_fields<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, mut f: impl FnMut(Option, FieldIdx, Ty<'tcx>), ) { match ty.kind() { @@ -892,20 +892,20 @@ pub fn iter_fields<'tcx>( for (f_index, f_def) in v_def.fields.iter().enumerate() { let field_ty = f_def.ty(tcx, args); let field_ty = tcx - .try_normalize_erasing_regions(param_env, field_ty) + .try_normalize_erasing_regions(typing_env, field_ty) .unwrap_or_else(|_| tcx.erase_regions(field_ty)); f(variant, f_index.into(), field_ty); } } } ty::Closure(_, args) => { - iter_fields(args.as_closure().tupled_upvars_ty(), tcx, param_env, f); + iter_fields(args.as_closure().tupled_upvars_ty(), tcx, typing_env, f); } ty::Coroutine(_, args) => { - iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, param_env, f); + iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, typing_env, f); } ty::CoroutineClosure(_, args) => { - iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, param_env, f); + iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, typing_env, f); } _ => (), } 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 559df222a50..12a2fe23b14 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,6 +1,6 @@ use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use tracing::debug; use crate::util; @@ -40,10 +40,10 @@ pub(super) struct AddMovesForPackedDrops; 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 def_id = body.source.def_id(); let mut patch = MirPatch::new(body); - let param_env = tcx.param_env(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()); for (bb, data) in body.basic_blocks.iter_enumerated() { let loc = Location { block: bb, statement_index: data.statements.len() }; @@ -51,7 +51,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { match terminator.kind { TerminatorKind::Drop { place, .. } - if util::is_disaligned(tcx, body, param_env, place) => + if util::is_disaligned(tcx, body, typing_env, place) => { add_move_for_packed_drop( tcx, diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index 1922d4fef25..e9b85ba6e9d 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -9,9 +9,9 @@ pub(super) struct CheckPackedRef; impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { - let param_env = tcx.param_env(body.source.def_id()); + let typing_env = body.typing_env(tcx); let source_info = SourceInfo::outermost(body.span); - let mut checker = PackedRefChecker { body, tcx, param_env, source_info }; + let mut checker = PackedRefChecker { body, tcx, typing_env, source_info }; checker.visit_body(body); } } @@ -19,7 +19,7 @@ impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef { struct PackedRefChecker<'a, 'tcx> { body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, source_info: SourceInfo, } @@ -37,7 +37,8 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { } fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.param_env, *place) { + if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place) + { let def_id = self.body.source.instance.def_id(); if let Some(impl_def_id) = self.tcx.impl_of_method(def_id) && self.tcx.is_builtin_derived(impl_def_id) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index c2666caa1e8..d38a1dd11dc 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1069,11 +1069,9 @@ fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Note that `elaborate_drops` only drops the upvars of a coroutine, and // this is ok because `open_drop` can only be reached within that own // coroutine's resume function. + let typing_env = body.typing_env(tcx); - let def_id = body.source.def_id(); - let param_env = tcx.param_env(def_id); - - let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env }; + let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, typing_env }; for (block, block_data) in body.basic_blocks.iter_enumerated() { let (target, unwind, source_info) = match block_data.terminator() { @@ -1204,9 +1202,9 @@ fn insert_panic_block<'tcx>( insert_term_block(body, kind) } -fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { +fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Returning from a function with an uninhabited return type is undefined behavior. - if body.return_ty().is_privately_uninhabited(tcx, param_env) { + if body.return_ty().is_privately_uninhabited(tcx, typing_env) { return false; } @@ -1627,7 +1625,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { // `storage_liveness` tells us which locals have live storage at suspension points let (remap, layout, storage_liveness) = compute_layout(liveness_info, body); - let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id())); + let can_return = can_return(tcx, body, body.typing_env(tcx)); // Run the transformation which converts Places from Local to coroutine struct // accesses for locals in `remap`. diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index 59b403538a3..b23d8b9e737 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -1,7 +1,7 @@ use rustc_middle::bug; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; const INSTR_COST: usize = 5; const CALL_PENALTY: usize = 25; @@ -14,7 +14,7 @@ const CONST_SWITCH_BONUS: usize = 10; #[derive(Clone)] pub(super) struct CostChecker<'b, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, penalty: usize, bonus: usize, callee_body: &'b Body<'tcx>, @@ -24,11 +24,11 @@ pub(super) struct CostChecker<'b, 'tcx> { impl<'b, 'tcx> CostChecker<'b, 'tcx> { pub(super) fn new( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, instance: Option>, callee_body: &'b Body<'tcx>, ) -> CostChecker<'b, 'tcx> { - CostChecker { tcx, param_env, callee_body, instance, penalty: 0, bonus: 0 } + CostChecker { tcx, typing_env, callee_body, instance, penalty: 0, bonus: 0 } } /// Add function-level costs not well-represented by the block-level costs. @@ -119,7 +119,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { TerminatorKind::Drop { place, unwind, .. } => { // If the place doesn't actually need dropping, treat it like a regular goto. let ty = self.instantiate_ty(place.ty(self.callee_body, self.tcx).ty); - if ty.needs_drop(self.tcx, self.param_env) { + if ty.needs_drop(self.tcx, self.typing_env) { self.penalty += CALL_PENALTY; if let UnwindAction::Cleanup(_) = unwind { self.penalty += LANDINGPAD_PENALTY; diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index ab6460c490b..500515bc3cc 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -16,7 +16,7 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::lattice::{FlatSet, HasBottom}; @@ -82,7 +82,7 @@ struct ConstAnalysis<'a, 'tcx> { tcx: TyCtxt<'tcx>, local_decls: &'a LocalDecls<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { @@ -144,13 +144,13 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); Self { map, tcx, local_decls: &body.local_decls, - ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), - param_env, + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), + typing_env, } } @@ -389,7 +389,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { && let Some(operand_ty) = operand_ty.builtin_deref(true) && let ty::Array(_, len) = operand_ty.kind() && let Some(len) = Const::Ty(self.tcx.types.usize, *len) - .try_eval_scalar_int(self.tcx, self.param_env) + .try_eval_scalar_int(self.tcx, self.typing_env) { state.insert_value_idx(target_len, FlatSet::Elem(len.into()), &self.map); } @@ -411,7 +411,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { let place_ty = place.ty(self.local_decls, self.tcx); if let ty::Array(_, len) = place_ty.ty.kind() { Const::Ty(self.tcx.types.usize, *len) - .try_eval_scalar(self.tcx, self.param_env) + .try_eval_scalar(self.tcx, self.typing_env) .map_or(FlatSet::Top, FlatSet::Elem) } else if let [ProjectionElem::Deref] = place.projection[..] { state.get_len(place.local.into(), &self.map) @@ -420,7 +420,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => { - let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else { + let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); }; match self.eval_operand(operand, state) { @@ -434,7 +434,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => { - let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else { + let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); }; match self.eval_operand(operand, state) { @@ -470,7 +470,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { FlatSet::Top => FlatSet::Top, }, Rvalue::NullaryOp(null_op, ty) => { - let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else { + let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); }; let val = match null_op { @@ -479,7 +479,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { NullOp::OffsetOf(fields) => self .ecx .tcx - .offset_of_subfield(self.ecx.param_env(), layout, fields.iter()) + .offset_of_subfield(self.typing_env, layout, fields.iter()) .bytes(), _ => return ValueOrPlace::Value(FlatSet::Top), }; @@ -514,7 +514,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { ) -> FlatSet { constant .const_ - .try_eval_scalar(self.tcx, self.param_env) + .try_eval_scalar(self.tcx, self.typing_env) .map_or(FlatSet::Top, FlatSet::Elem) } @@ -554,7 +554,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } else if rhs.projection.first() == Some(&PlaceElem::Deref) && let FlatSet::Elem(pointer) = state.get(rhs.local.into(), &self.map) && let rhs_ty = self.local_decls[rhs.local].ty - && let Ok(rhs_layout) = self.tcx.layout_of(self.param_env.and(rhs_ty)) + && let Ok(rhs_layout) = + self.tcx.layout_of(self.typing_env.as_query_input(rhs_ty)) { let op = ImmTy::from_scalar(pointer, rhs_layout).into(); self.assign_constant(state, place, op, rhs.projection); @@ -614,8 +615,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { TrackElem::DerefLen => { let op: OpTy<'_> = self.ecx.deref_pointer(op).discard_err()?.into(); let len_usize = op.len(&self.ecx).discard_err()?; - let layout = - self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).unwrap(); + let layout = self + .tcx + .layout_of(self.typing_env.as_query_input(self.tcx.types.usize)) + .unwrap(); Some(ImmTy::from_uint(len_usize, layout).into()) } }, @@ -702,9 +705,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { FlatSet::Top => FlatSet::Top, FlatSet::Elem(scalar) => { let ty = op.ty(self.local_decls, self.tcx); - self.tcx.layout_of(self.param_env.and(ty)).map_or(FlatSet::Top, |layout| { - FlatSet::Elem(ImmTy::from_scalar(scalar, layout)) - }) + self.tcx + .layout_of(self.typing_env.as_query_input(ty)) + .map_or(FlatSet::Top, |layout| { + FlatSet::Elem(ImmTy::from_scalar(scalar, layout)) + }) } FlatSet::Bottom => FlatSet::Bottom, } @@ -714,7 +719,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { if !enum_ty.is_enum() { return None; } - let enum_ty_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?; + let enum_ty_layout = self.tcx.layout_of(self.typing_env.as_query_input(enum_ty)).ok()?; let discr_value = self.ecx.discriminant_for_variant(enum_ty_layout.ty, variant_index).discard_err()?; Some(discr_value.to_scalar()) diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 753bae8e156..db72ec522a2 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -198,7 +198,7 @@ pub(super) fn deduced_param_attrs<'tcx>( // see [1]. // // [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997 - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let typing_env = body.typing_env(tcx); let mut deduced_param_attrs = tcx.arena.alloc_from_iter( body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map( |(arg_index, local_decl)| DeducedParamAttrs { @@ -207,8 +207,8 @@ pub(super) fn deduced_param_attrs<'tcx>( // their generic parameters, otherwise we'll see exponential // blow-up in compile times: #113372 && tcx - .normalize_erasing_regions(param_env, local_decl.ty) - .is_freeze(tcx, param_env), + .normalize_erasing_regions(typing_env, local_decl.ty) + .is_freeze(tcx, typing_env.param_env), }, ), ); diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 74572100db3..b0f041d8722 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -3,6 +3,7 @@ use std::fmt; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_index::IndexVec; use rustc_index::bit_set::BitSet; +use rustc_infer::traits::Reveal; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; @@ -53,14 +54,14 @@ 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); - - let def_id = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(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()); // 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, param_env)); + let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env)); let elaborate_patch = { - let env = MoveDataParamEnv { move_data, param_env }; + let env = MoveDataParamEnv { move_data, param_env: typing_env.param_env }; let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data) .skipping_unreachable_unwind() @@ -147,8 +148,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> { self.tcx } - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env() + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env() } #[instrument(level = "debug", skip(self), ret)] @@ -250,6 +251,11 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { self.env.param_env } + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + debug_assert_eq!(self.param_env().reveal(), Reveal::All); + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env() } + } + fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) { let patch = &mut self.patch; debug!("create_drop_flag({:?})", self.body.span); @@ -335,7 +341,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { if !place .ty(&self.body.local_decls, self.tcx) .ty - .needs_drop(self.tcx, self.env.param_env) + .needs_drop(self.tcx, self.typing_env()) { self.patch.patch_terminator(bb, TerminatorKind::Goto { target }); continue; diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 274eea9563f..27fe0ad72e7 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -100,7 +100,7 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::GlobalAlloc; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; @@ -295,6 +295,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } + } + #[instrument(level = "trace", skip(self), ret)] fn insert(&mut self, value: Value<'tcx>) -> VnIndex { let (index, new) = self.values.insert_full(value); @@ -531,7 +535,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { NullOp::OffsetOf(fields) => self .ecx .tcx - .offset_of_subfield(self.ecx.param_env(), layout, fields.iter()) + .offset_of_subfield(self.typing_env(), layout, fields.iter()) .bytes(), NullOp::UbChecks => return None, }; @@ -1476,8 +1480,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if left_meta_ty == right_meta_ty { true } else if let Ok(left) = - self.tcx.try_normalize_erasing_regions(self.param_env, left_meta_ty) - && let Ok(right) = self.tcx.try_normalize_erasing_regions(self.param_env, right_meta_ty) + self.tcx.try_normalize_erasing_regions(self.typing_env(), left_meta_ty) + && let Ok(right) = + self.tcx.try_normalize_erasing_regions(self.typing_env(), right_meta_ty) { left == right } else { diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index e95ab4ffe16..fcb51fbddd9 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -13,9 +13,7 @@ use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::{ - self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeFlags, TypeVisitableExt, -}; +use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::source_map::Spanned; use rustc_span::sym; @@ -94,12 +92,12 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { return false; } - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let typing_env = body.typing_env(tcx); let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id); let mut this = Inliner { tcx, - param_env, + typing_env, codegen_fn_attrs, history: Vec::new(), changed: false, @@ -115,7 +113,7 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { struct Inliner<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, /// Caller codegen attributes. codegen_fn_attrs: &'tcx CodegenFnAttrs, /// Stack of inlined instances. @@ -201,7 +199,11 @@ impl<'tcx> Inliner<'tcx> { let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty; for arg in args { - if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) { + if !arg + .node + .ty(&caller_body.local_decls, self.tcx) + .is_sized(self.tcx, self.typing_env.param_env) + { // We do not allow inlining functions with unsized params. Inlining these functions // could create unsized locals, which are unsound and being phased out. return Err("Call has unsized argument"); @@ -219,7 +221,7 @@ impl<'tcx> Inliner<'tcx> { let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions( self.tcx, - self.param_env, + self.typing_env, ty::EarlyBinder::bind(callee_body.clone()), ) else { return Err("failed to normalize callee body"); @@ -230,7 +232,7 @@ impl<'tcx> Inliner<'tcx> { if !validate_types( self.tcx, MirPhase::Runtime(RuntimePhase::Optimized), - self.param_env, + self.typing_env, &callee_body, &caller_body, ) @@ -243,13 +245,7 @@ impl<'tcx> Inliner<'tcx> { // Normally, this shouldn't be required, but trait normalization failure can create a // validation ICE. let output_type = callee_body.return_ty(); - if !util::sub_types( - self.tcx, - caller_body.typing_mode(self.tcx), - self.param_env, - output_type, - destination_ty, - ) { + if !util::sub_types(self.tcx, self.typing_env, output_type, destination_ty) { trace!(?output_type, ?destination_ty); return Err("failed to normalize return type"); } @@ -279,13 +275,7 @@ impl<'tcx> Inliner<'tcx> { self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter()) { let input_type = callee_body.local_decls[input].ty; - if !util::sub_types( - self.tcx, - caller_body.typing_mode(self.tcx), - self.param_env, - input_type, - arg_ty, - ) { + if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) { trace!(?arg_ty, ?input_type); return Err("failed to normalize tuple argument type"); } @@ -294,13 +284,7 @@ impl<'tcx> Inliner<'tcx> { for (arg, input) in args.iter().zip(callee_body.args_iter()) { let input_type = callee_body.local_decls[input].ty; let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx); - if !util::sub_types( - self.tcx, - caller_body.typing_mode(self.tcx), - self.param_env, - input_type, - arg_ty, - ) { + if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) { trace!(?arg_ty, ?input_type); return Err("failed to normalize argument type"); } @@ -402,9 +386,10 @@ impl<'tcx> Inliner<'tcx> { let func_ty = func.ty(caller_body, self.tcx); if let ty::FnDef(def_id, args) = *func_ty.kind() { // To resolve an instance its args have to be fully normalized. - let args = self.tcx.try_normalize_erasing_regions(self.param_env, args).ok()?; - let callee = - Instance::try_resolve(self.tcx, self.param_env, def_id, args).ok().flatten()?; + let args = self.tcx.try_normalize_erasing_regions(self.typing_env, args).ok()?; + let callee = Instance::try_resolve(self.tcx, self.typing_env, def_id, args) + .ok() + .flatten()?; if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def { return None; @@ -528,7 +513,7 @@ impl<'tcx> Inliner<'tcx> { // FIXME: Give a bonus to functions with only a single caller let mut checker = - CostChecker::new(self.tcx, self.param_env, Some(callsite.callee), callee_body); + CostChecker::new(self.tcx, self.typing_env, Some(callsite.callee), callee_body); checker.add_function_level_costs(); @@ -552,7 +537,7 @@ impl<'tcx> Inliner<'tcx> { self.tcx, ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty), ); - if ty.needs_drop(tcx, self.param_env) + if ty.needs_drop(tcx, self.typing_env) && let UnwindAction::Cleanup(unwind) = unwind { work_list.push(unwind); diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 9828e90de88..a40768300f5 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -15,7 +15,6 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( (root, target): (ty::Instance<'tcx>, LocalDefId), ) -> bool { trace!(%root, target = %tcx.def_path_str(target)); - let param_env = tcx.param_env_reveal_all_normalized(target); assert_ne!( root.def_id().expect_local(), target, @@ -31,11 +30,11 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( ); #[instrument( level = "debug", - skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit) + skip(tcx, typing_env, target, stack, seen, recursion_limiter, caller, recursion_limit) )] fn process<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, caller: ty::Instance<'tcx>, target: LocalDefId, stack: &mut Vec>, @@ -47,13 +46,13 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( for &(callee, args) in tcx.mir_inliner_callees(caller.def) { let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions( tcx, - param_env, + typing_env, ty::EarlyBinder::bind(args), ) else { - trace!(?caller, ?param_env, ?args, "cannot normalize, skipping"); + trace!(?caller, ?typing_env, ?args, "cannot normalize, skipping"); continue; }; - let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, param_env, callee, args) else { + let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee, args) else { trace!(?callee, "cannot resolve, skipping"); continue; }; @@ -115,7 +114,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( let found_recursion = ensure_sufficient_stack(|| { process( tcx, - param_env, + typing_env, callee, target, stack, @@ -146,7 +145,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( let recursion_limit = tcx.recursion_limit() / 2; process( tcx, - param_env, + ty::TypingEnv::post_analysis(tcx, target), root, target, &mut Vec::new(), diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 9471c1b2a9a..b80abcca969 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -69,6 +69,12 @@ struct InstSimplifyContext<'a, 'tcx> { param_env: ParamEnv<'tcx>, } +impl<'tcx> InstSimplifyContext<'_, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } + } +} + impl<'tcx> InstSimplifyContext<'_, 'tcx> { fn should_simplify(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool { self.should_simplify_custom(source_info, "Rvalue", rvalue) @@ -348,7 +354,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } let known_is_valid = - intrinsic_assert_panics(self.tcx, self.param_env, args[0], intrinsic_name); + intrinsic_assert_panics(self.tcx, self.typing_env(), args[0], intrinsic_name); match known_is_valid { // We don't know the layout or it's not validity assertion at all, don't touch it None => {} @@ -366,13 +372,13 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { fn intrinsic_assert_panics<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, arg: ty::GenericArg<'tcx>, intrinsic_name: Symbol, ) -> Option { let requirement = ValidityRequirement::from_intrinsic(intrinsic_name)?; let ty = arg.expect_ty(); - Some(!tcx.check_validity_requirement((requirement, param_env.and(ty))).ok()?) + Some(!tcx.check_validity_requirement((requirement, typing_env.as_query_input(ty))).ok()?) } fn resolve_rust_intrinsic<'tcx>( diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 3772589ac4e..71a843a785c 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -77,13 +77,12 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { return; } - let param_env = tcx.param_env_reveal_all_normalized(def_id); - + let typing_env = body.typing_env(tcx); let arena = &DroplessArena::default(); let mut finder = TOFinder { tcx, - param_env, - ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), + typing_env, + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), body, arena, map: Map::new(tcx, body, Some(MAX_PLACES)), @@ -119,7 +118,7 @@ struct ThreadingOpportunity { struct TOFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, body: &'a Body<'tcx>, map: Map<'tcx>, @@ -207,7 +206,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { let Some(discr) = self.map.find(discr.as_ref()) else { return }; debug!(?discr); - let cost = CostChecker::new(self.tcx, self.param_env, None, self.body); + let cost = CostChecker::new(self.tcx, self.typing_env, None, self.body); let mut state = State::new_reachable(); let conds = if let Some((value, then, else_)) = targets.as_static_if() { @@ -528,7 +527,8 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { // Avoid handling them, though this could be extended in the future. return; } - let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.param_env) else { + let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.typing_env) + else { return; }; let conds = conditions.map(self.arena, |c| Condition { diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 0604665642a..3911b0a2db6 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -18,7 +18,7 @@ use rustc_middle::bug; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; -use rustc_middle::ty::{self, ConstInt, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, ConstInt, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::Span; use tracing::{debug, instrument, trace}; @@ -65,7 +65,7 @@ impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint { struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'tcx, DummyMachine>, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, worklist: Vec, visited_blocks: BitSet, locals: IndexVec>, @@ -169,25 +169,26 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'_, 'tcx> { } } -impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> { +impl<'tcx> ty::layout::HasTypingEnv<'tcx> for ConstPropagator<'_, 'tcx> { #[inline] - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env } } 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(); - let param_env = tcx.param_env_reveal_all_normalized(def_id); - - let can_const_prop = CanConstProp::check(tcx, param_env, body); - let ecx = InterpCx::new(tcx, tcx.def_span(def_id), param_env, DummyMachine); + // 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 can_const_prop = CanConstProp::check(tcx, typing_env, body); + let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env.param_env, DummyMachine); ConstPropagator { ecx, tcx, - param_env, + typing_env, worklist: vec![START_BLOCK], visited_blocks: BitSet::new_empty(body.basic_blocks.len()), locals: IndexVec::from_elem_n(Value::Uninit, body.local_decls.len()), @@ -260,7 +261,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // that the `RevealAll` pass has happened and that the body's consts // are normalized, so any call to resolve before that needs to be // manually normalized. - let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.const_).ok()?; + let val = self.tcx.try_normalize_erasing_regions(self.typing_env, c.const_).ok()?; self.use_ecx(|this| this.ecx.eval_mir_constant(&val, c.span, None))? .as_mplace_or_imm() @@ -450,7 +451,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if rvalue.has_param() { return None; } - if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.param_env) { + if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env.param_env) { // the interpreter doesn't support unsized locals (only unsized arguments), // but rustc does (in a kinda broken way), so we have to skip them here return None; @@ -622,7 +623,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { NullOp::AlignOf => op_layout.align.abi.bytes(), NullOp::OffsetOf(fields) => self .tcx - .offset_of_subfield(self.param_env, op_layout, fields.iter()) + .offset_of_subfield(self.typing_env, op_layout, fields.iter()) .bytes(), NullOp::UbChecks => return None, }; @@ -873,7 +874,7 @@ impl CanConstProp { /// Returns true if `local` can be propagated fn check<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, body: &Body<'tcx>, ) -> IndexVec { let mut cpv = CanConstProp { @@ -888,7 +889,7 @@ impl CanConstProp { // variant of a union *val = ConstPropMode::NoPropagation; } else { - match tcx.layout_of(param_env.and(ty)) { + match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {} // Either the layout fails to compute, then we can't use this local anyway // or the local is too large, then we don't want to. diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index fa659a56a27..8be5a63d008 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::*; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_session::Session; /// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large @@ -39,8 +39,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { // platform, but it will still be valid. let mut alloc_cache = FxHashMap::default(); - let body_did = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(body_did); + let typing_env = body.typing_env(tcx); let blocks = body.basic_blocks.as_mut(); let local_decls = &mut body.local_decls; @@ -58,7 +57,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { let ty = lhs.ty(local_decls, tcx).ty; let (adt_def, num_variants, alloc_id) = - self.candidate(tcx, param_env, ty, &mut alloc_cache)?; + self.candidate(tcx, typing_env, ty, &mut alloc_cache)?; let source_info = st.source_info; let span = source_info.span; @@ -207,7 +206,7 @@ impl EnumSizeOpt { fn candidate<'tcx>( &self, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, alloc_cache: &mut FxHashMap, AllocId>, ) -> Option<(AdtDef<'tcx>, usize, AllocId)> { @@ -215,7 +214,7 @@ impl EnumSizeOpt { ty::Adt(adt_def, _args) if adt_def.is_enum() => adt_def, _ => return None, }; - let layout = tcx.layout_of(param_env.and(ty)).ok()?; + let layout = tcx.layout_of(typing_env.as_query_input(ty)).ok()?; let variants = match &layout.variants { Variants::Single { .. } => return None, Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => return None, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index d2d5facbbdc..5651bf469d5 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -333,10 +333,14 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { } fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { - let const_kind = tcx.hir().body_const_context(def); - + // N.B., this `borrow()` is guaranteed to be valid (i.e., the value + // cannot yet be stolen), because `mir_promoted()`, which steals + // from `mir_built()`, forces this query to execute before + // performing the steal. + let body = &tcx.mir_built(def).borrow(); + let ccx = check_consts::ConstCx::new(tcx, body); // No need to const-check a non-const `fn`. - match const_kind { + match ccx.const_kind { Some(ConstContext::Const { .. } | ConstContext::Static(_) | ConstContext::ConstFn) => {} None => span_bug!( tcx.def_span(def), @@ -344,20 +348,12 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { ), } - // N.B., this `borrow()` is guaranteed to be valid (i.e., the value - // cannot yet be stolen), because `mir_promoted()`, which steals - // from `mir_built()`, forces this query to execute before - // performing the steal. - let body = &tcx.mir_built(def).borrow(); - if body.return_ty().references_error() { // It's possible to reach here without an error being emitted (#121103). tcx.dcx().span_delayed_bug(body.span, "mir_const_qualif: MIR had errors"); return Default::default(); } - let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def) }; - let mut validator = check_consts::check::Checker::new(&ccx); validator.check_body(); diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 237227f5294..ff027680c49 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -5,7 +5,7 @@ use rustc_index::IndexSlice; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; -use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt}; +use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_type_ir::TyKind::*; use super::simplify::simplify_cfg; @@ -19,8 +19,7 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(def_id); - + let typing_env = body.typing_env(tcx); let mut should_cleanup = false; for i in 0..body.basic_blocks.len() { let bbs = &*body.basic_blocks; @@ -40,11 +39,11 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { _ => continue, }; - if SimplifyToIf.simplify(tcx, body, bb_idx, param_env).is_some() { + if SimplifyToIf.simplify(tcx, body, bb_idx, typing_env).is_some() { should_cleanup = true; continue; } - if SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() { + if SimplifyToExp::default().simplify(tcx, body, bb_idx, typing_env).is_some() { should_cleanup = true; continue; } @@ -65,7 +64,7 @@ trait SimplifyMatch<'tcx> { tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, switch_bb_idx: BasicBlock, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option<()> { let bbs = &body.basic_blocks; let (discr, targets) = match bbs[switch_bb_idx].terminator().kind { @@ -74,7 +73,7 @@ trait SimplifyMatch<'tcx> { }; let discr_ty = discr.ty(body.local_decls(), tcx); - self.can_simplify(tcx, targets, param_env, bbs, discr_ty)?; + self.can_simplify(tcx, targets, typing_env, bbs, discr_ty)?; let mut patch = MirPatch::new(body); @@ -90,7 +89,16 @@ trait SimplifyMatch<'tcx> { let parent_end = Location { block: switch_bb_idx, statement_index }; patch.add_statement(parent_end, StatementKind::StorageLive(discr_local)); patch.add_assign(parent_end, Place::from(discr_local), Rvalue::Use(discr)); - self.new_stmts(tcx, targets, param_env, &mut patch, parent_end, bbs, discr_local, discr_ty); + self.new_stmts( + tcx, + targets, + typing_env, + &mut patch, + parent_end, + bbs, + discr_local, + discr_ty, + ); patch.add_statement(parent_end, StatementKind::StorageDead(discr_local)); patch.patch_terminator(switch_bb_idx, bbs[first].terminator().kind.clone()); patch.apply(body); @@ -104,7 +112,7 @@ trait SimplifyMatch<'tcx> { &mut self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, bbs: &IndexSlice>, discr_ty: Ty<'tcx>, ) -> Option<()>; @@ -113,7 +121,7 @@ trait SimplifyMatch<'tcx> { &self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, patch: &mut MirPatch<'tcx>, parent_end: Location, bbs: &IndexSlice>, @@ -160,7 +168,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { &mut self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, bbs: &IndexSlice>, _discr_ty: Ty<'tcx>, ) -> Option<()> { @@ -197,8 +205,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { ) if lhs_f == lhs_s && f_c.const_.ty().is_bool() && s_c.const_.ty().is_bool() - && f_c.const_.try_eval_bool(tcx, param_env).is_some() - && s_c.const_.try_eval_bool(tcx, param_env).is_some() => {} + && f_c.const_.try_eval_bool(tcx, typing_env).is_some() + && s_c.const_.try_eval_bool(tcx, typing_env).is_some() => {} // Otherwise we cannot optimize. Try another block. _ => return None, @@ -211,7 +219,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { &self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, patch: &mut MirPatch<'tcx>, parent_end: Location, bbs: &IndexSlice>, @@ -235,15 +243,15 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))), ) => { // From earlier loop we know that we are dealing with bool constants only: - let f_b = f_c.const_.try_eval_bool(tcx, param_env).unwrap(); - let s_b = s_c.const_.try_eval_bool(tcx, param_env).unwrap(); + let f_b = f_c.const_.try_eval_bool(tcx, typing_env).unwrap(); + let s_b = s_c.const_.try_eval_bool(tcx, typing_env).unwrap(); if f_b == s_b { // Same value in both blocks. Use statement as is. patch.add_statement(parent_end, f.kind.clone()); } else { // Different value between blocks. Make value conditional on switch // condition. - let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size; + let size = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap().size; let const_cmp = Operand::const_from_scalar( tcx, discr_ty, @@ -363,7 +371,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { &mut self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, bbs: &IndexSlice>, discr_ty: Ty<'tcx>, ) -> Option<()> { @@ -388,7 +396,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { return None; } - let discr_layout = tcx.layout_of(param_env.and(discr_ty)).unwrap(); + let discr_layout = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap(); let first_stmts = &bbs[first_target].statements; let (second_case_val, second_target) = target_iter.next().unwrap(); let second_stmts = &bbs[second_target].statements; @@ -414,8 +422,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { && f_c.const_.ty().is_integral() => { match ( - f_c.const_.try_eval_scalar_int(tcx, param_env), - s_c.const_.try_eval_scalar_int(tcx, param_env), + f_c.const_.try_eval_scalar_int(tcx, typing_env), + s_c.const_.try_eval_scalar_int(tcx, typing_env), ) { (Some(f), Some(s)) if f == s => ExpectedTransformKind::SameByEq { place: lhs_f, @@ -467,11 +475,11 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), ) if lhs_f == lhs_s && s_c.const_.ty() == f_ty - && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(scalar) => {} + && s_c.const_.try_eval_scalar_int(tcx, typing_env) == Some(scalar) => {} ( ExpectedTransformKind::Cast { place: lhs_f, ty: f_ty }, StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), - ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env) + ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, typing_env) && lhs_f == lhs_s && s_c.const_.ty() == f_ty && can_cast(tcx, other_val, discr_layout, f_ty, f) => {} @@ -487,7 +495,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { &self, _tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - _param_env: ParamEnv<'tcx>, + _typing_env: ty::TypingEnv<'tcx>, patch: &mut MirPatch<'tcx>, parent_end: Location, bbs: &IndexSlice>, diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index fa9a6bfcf7c..6be95b1f0f1 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -325,7 +325,7 @@ impl<'tcx> Validator<'_, 'tcx> { if let TempState::Defined { location: loc, .. } = self.temps[local] && let Left(statement) = self.body.stmt_at(loc) && let Some((_, Rvalue::Use(Operand::Constant(c)))) = statement.kind.as_assign() - && let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.param_env) + && let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.typing_env) // Determine the type of the thing we are indexing. && let ty::Array(_, len) = place_base.ty(self.body, self.tcx).ty.kind() // It's an array; determine its length. @@ -490,7 +490,7 @@ impl<'tcx> Validator<'_, 'tcx> { // Integer division: the RHS must be a non-zero const. let rhs_val = match rhs { Operand::Constant(c) => { - c.const_.try_eval_scalar_int(self.tcx, self.param_env) + c.const_.try_eval_scalar_int(self.tcx, self.typing_env) } _ => None, }; @@ -509,7 +509,7 @@ impl<'tcx> Validator<'_, 'tcx> { let lhs_val = match lhs { Operand::Constant(c) => c .const_ - .try_eval_scalar_int(self.tcx, self.param_env), + .try_eval_scalar_int(self.tcx, self.typing_env), _ => None, }; let lhs_min = sz.signed_int_min(); diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 20c34a7469e..f786c676e9e 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -1,7 +1,7 @@ use rustc_abi::FieldIdx; use rustc_index::bit_set::ChunkedBitSet; use rustc_middle::mir::{Body, TerminatorKind}; -use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, VariantDef}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{Analysis, MaybeReachable, move_path_children_matching}; @@ -18,8 +18,8 @@ pub(super) struct RemoveUninitDrops; impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env(body.source.def_id()); - let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env)); + let typing_env = body.typing_env(tcx); + let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env)); let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) .iterate_to_fixpoint(tcx, body, Some("remove_uninit_drops")) @@ -40,7 +40,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { let should_keep = is_needs_drop_and_init( tcx, - param_env, + typing_env, maybe_inits, &move_data, place.ty(body, tcx).ty, @@ -66,24 +66,24 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { fn is_needs_drop_and_init<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, maybe_inits: &ChunkedBitSet, move_data: &MoveData<'tcx>, ty: Ty<'tcx>, mpi: MovePathIndex, ) -> bool { // No need to look deeper if the root is definitely uninit or if it has no `Drop` impl. - if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, param_env) { + if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, typing_env) { return false; } let field_needs_drop_and_init = |(f, f_ty, mpi)| { let child = move_path_children_matching(move_data, mpi, |x| x.is_field_to(f)); let Some(mpi) = child else { - return Ty::needs_drop(f_ty, tcx, param_env); + return Ty::needs_drop(f_ty, tcx, typing_env); }; - is_needs_drop_and_init(tcx, param_env, maybe_inits, move_data, f_ty, mpi) + is_needs_drop_and_init(tcx, typing_env, maybe_inits, move_data, f_ty, mpi) }; // This pass is only needed for const-checking, so it doesn't handle as many cases as @@ -110,7 +110,7 @@ fn is_needs_drop_and_init<'tcx>( let downcast = move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid)); let Some(dc_mpi) = downcast else { - return variant_needs_drop(tcx, param_env, args, variant); + return variant_needs_drop(tcx, typing_env, args, variant); }; dc_mpi @@ -139,12 +139,12 @@ fn is_needs_drop_and_init<'tcx>( fn variant_needs_drop<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, args: GenericArgsRef<'tcx>, variant: &VariantDef, ) -> bool { variant.fields.iter().any(|field| { let f_ty = field.ty(tcx, args); - f_ty.needs_drop(tcx, param_env) + f_ty.needs_drop(tcx, typing_env) }) } diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 28925ba1beb..ad62b47a66d 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -16,18 +16,18 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running RemoveUnneededDrops on {:?}", body.source); - let did = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(did); + let typing_env = body.typing_env(tcx); let mut should_simplify = false; - for block in body.basic_blocks.as_mut() { let terminator = block.terminator_mut(); if let TerminatorKind::Drop { place, target, .. } = terminator.kind { let ty = place.ty(&body.local_decls, tcx); - if ty.ty.needs_drop(tcx, param_env) { + if ty.ty.needs_drop(tcx, typing_env) { continue; } - if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {did:?} ")) { + if !tcx.consider_optimizing(|| { + format!("RemoveUnneededDrops {:?}", body.source.def_id()) + }) { continue; } debug!("SUCCESS: replacing `drop` with goto({:?})", target); diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index f13bb1c5993..2f723bccc19 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -21,9 +21,9 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { return; } - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); let local_decls = &body.local_decls; - let mut replacer = Replacer { tcx, param_env, local_decls }; + let mut replacer = Replacer { tcx, typing_env, local_decls }; for var_debug_info in &mut body.var_debug_info { replacer.visit_var_debug_info(var_debug_info); } @@ -35,7 +35,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { struct Replacer<'a, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, local_decls: &'a LocalDecls<'tcx>, } @@ -61,7 +61,7 @@ impl<'tcx> Replacer<'_, 'tcx> { if !maybe_zst(ty) { return false; } - let Ok(layout) = self.tcx.layout_of(self.param_env.and(ty)) else { + let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(ty)) else { return false; }; layout.is_zst() diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index f3b2f78b31c..587032ee720 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -8,14 +8,16 @@ pub(super) struct RevealAll; impl<'tcx> crate::MirPass<'tcx> for RevealAll { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(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()); + RevealAllVisitor { tcx, typing_env }.visit_body_preserves_cfg(body); } } struct RevealAllVisitor<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { @@ -53,7 +55,7 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { // We have to use `try_normalize_erasing_regions` here, since it's // possible that we visit impossible-to-satisfy where clauses here, // see #91745 - if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) { + if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.typing_env, constant.const_) { constant.const_ = c; } self.super_const_operand(constant, location); @@ -64,7 +66,7 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { // We have to use `try_normalize_erasing_regions` here, since it's // possible that we visit impossible-to-satisfy where clauses here, // see #91745 - if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.param_env, *ty) { + if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.typing_env, *ty) { *ty = t; } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index ffa11f5b213..f16cde7cd4e 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -274,9 +274,9 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) if ty.is_some() { let patch = { - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, def_id); let mut elaborator = - DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, param_env }; + DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, typing_env }; let dropee = tcx.mk_place_deref(dropee_ptr); let resume_block = elaborator.patch.resume_block(); elaborate_drops::elaborate_drop( @@ -334,7 +334,7 @@ pub(super) struct DropShimElaborator<'a, 'tcx> { pub body: &'a Body<'tcx>, pub patch: MirPatch<'tcx>, pub tcx: TyCtxt<'tcx>, - pub param_env: ty::ParamEnv<'tcx>, + pub typing_env: ty::TypingEnv<'tcx>, } impl fmt::Debug for DropShimElaborator<'_, '_> { @@ -355,8 +355,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env } fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle { @@ -914,7 +914,7 @@ fn build_call_shim<'tcx>( pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { debug_assert!(tcx.is_constructor(ctor_id)); - let param_env = tcx.param_env_reveal_all_normalized(ctor_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id); // Normalize the sig. let sig = tcx @@ -922,7 +922,7 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { .instantiate_identity() .no_bound_vars() .expect("LBR in ADT constructor signature"); - let sig = tcx.normalize_erasing_regions(param_env, sig); + let sig = tcx.normalize_erasing_regions(typing_env, sig); let ty::Adt(adt_def, args) = sig.output().kind() else { bug!("unexpected type for ADT ctor {:?}", sig.output()); diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index f1672272862..139b25be0ab 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -48,7 +48,7 @@ struct AsyncDestructorCtorShimBuilder<'tcx> { self_ty: Option>, span: Span, source_info: SourceInfo, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, stack: Vec>, last_bb: BasicBlock, @@ -86,14 +86,14 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { // Usual case: noop() + unwind resume + return let mut bbs = IndexVec::with_capacity(3); - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, def_id); AsyncDestructorCtorShimBuilder { tcx, def_id, self_ty, span, source_info, - param_env, + typing_env, stack: Vec::with_capacity(Self::MAX_STACK_LEN), last_bb: bbs.push(BasicBlockData::new(None)), @@ -422,7 +422,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { statements: Vec::new(), terminator: Some(Terminator { source_info, - kind: if self.locals[local].ty.needs_drop(self.tcx, self.param_env) { + kind: if self.locals[local].ty.needs_drop(self.tcx, self.typing_env) { TerminatorKind::Drop { place: local.into(), target: *top_cleanup_bb, diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index e83b4727c48..bea3d0d8557 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -18,14 +18,14 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running SimplifyConstCondition on {:?}", body.source); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); 'blocks: for block in body.basic_blocks_mut() { for stmt in block.statements.iter_mut() { // Simplify `assume` of a known value: either a NOP or unreachable. if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind && let NonDivergingIntrinsic::Assume(discr) = intrinsic && let Operand::Constant(ref c) = discr - && let Some(constant) = c.const_.try_eval_bool(tcx, param_env) + && let Some(constant) = c.const_.try_eval_bool(tcx, typing_env) { if constant { stmt.make_nop(); @@ -42,7 +42,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { TerminatorKind::SwitchInt { discr: Operand::Constant(ref c), ref targets, .. } => { - let constant = c.const_.try_eval_bits(tcx, param_env); + let constant = c.const_.try_eval_bits(tcx, typing_env); if let Some(constant) = constant { let target = targets.target_for_value(constant); TerminatorKind::Goto { target } @@ -52,7 +52,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { } TerminatorKind::Assert { target, cond: Operand::Constant(ref c), expected, .. - } => match c.const_.try_eval_bool(tcx, param_env) { + } => match c.const_.try_eval_bool(tcx, typing_env) { Some(v) if v == expected => TerminatorKind::Goto { target }, _ => continue, }, diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 26496b7f3fe..b6d80173086 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -37,7 +37,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { let opts = helper.find_optimizations(); let mut storage_deads_to_insert = vec![]; let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![]; - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); for opt in opts { trace!("SUCCESS: Applying {:?}", opt); // replace terminator with a switchInt that switches on the integer directly @@ -46,7 +46,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { let new_value = match opt.branch_value_scalar { Scalar::Int(int) => { let layout = tcx - .layout_of(param_env.and(opt.branch_value_ty)) + .layout_of(typing_env.as_query_input(opt.branch_value_ty)) .expect("if we have an evaluated constant we must know the layout"); int.to_bits(layout.size) } diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 53bbb122096..52b9ec1e0a3 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -28,12 +28,12 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { } let mut excluded = excluded_locals(body); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); loop { debug!(?excluded); - let escaping = escaping_locals(tcx, param_env, &excluded, body); + let escaping = escaping_locals(tcx, typing_env, &excluded, body); debug!(?escaping); - let replacements = compute_flattening(tcx, param_env, body, escaping); + let replacements = compute_flattening(tcx, typing_env, body, escaping); debug!(?replacements); let all_dead_locals = replace_flattened_locals(tcx, body, replacements); if !all_dead_locals.is_empty() { @@ -59,7 +59,7 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { /// client code. fn escaping_locals<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, excluded: &BitSet, body: &Body<'tcx>, ) -> BitSet { @@ -84,7 +84,7 @@ fn escaping_locals<'tcx>( // niche, so we do not want to automatically exclude it. return false; } - let Ok(layout) = tcx.layout_of(param_env.and(ty)) else { + let Ok(layout) = tcx.layout_of(typing_env.as_query_input(ty)) else { // We can't get the layout return true; }; @@ -196,7 +196,7 @@ impl<'tcx> ReplacementMap<'tcx> { /// The replacement will be done later in `ReplacementVisitor`. fn compute_flattening<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, body: &mut Body<'tcx>, escaping: BitSet, ) -> ReplacementMap<'tcx> { @@ -208,7 +208,7 @@ fn compute_flattening<'tcx>( } let decl = body.local_decls[local].clone(); let ty = decl.ty; - iter_fields(ty, tcx, param_env, |variant, field, field_ty| { + iter_fields(ty, tcx, typing_env, |variant, field, field_ty| { if variant.is_some() { // Downcasts are currently not supported. return; diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 3011af4d9d7..57e255b7c32 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -92,9 +92,7 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching { let Some(discriminant_ty) = get_switched_on_type(bb_data, tcx, body) else { continue }; - let layout = tcx.layout_of( - tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty), - ); + let layout = tcx.layout_of(body.typing_env(tcx).as_query_input(discriminant_ty)); let mut allowed_variants = if let Ok(layout) = layout { // Find allowed variants based on uninhabited. diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index ae4e6ea6a74..ae0e6f594ee 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -12,8 +12,7 @@ use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{ - self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt, - Variance, + self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Variance, }; use rustc_middle::{bug, span_bug}; use rustc_trait_selection::traits::ObligationCtxt; @@ -47,9 +46,10 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) { return; } + debug_assert_eq!(self.mir_phase, body.phase); let def_id = body.source.def_id(); - let mir_phase = self.mir_phase; - let param_env = mir_phase.param_env(tcx, def_id); + let mir_phase = body.phase; + let typing_env = body.typing_env(tcx); let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) { // In this case `AbortUnwindingCalls` haven't yet been executed. true @@ -86,7 +86,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { cfg_checker.check_cleanup_control_flow(); // Also run the TypeChecker. - for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body, body) { + for (location, msg) in validate_types(tcx, self.mir_phase, typing_env, body, body) { cfg_checker.fail(location, msg); } @@ -532,12 +532,12 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { pub(super) fn validate_types<'tcx>( tcx: TyCtxt<'tcx>, mir_phase: MirPhase, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, body: &Body<'tcx>, caller_body: &Body<'tcx>, ) -> Vec<(Location, String)> { let mut type_checker = - TypeChecker { body, caller_body, tcx, param_env, mir_phase, failures: Vec::new() }; + TypeChecker { body, caller_body, tcx, typing_env, mir_phase, failures: Vec::new() }; type_checker.visit_body(body); type_checker.failures } @@ -546,7 +546,7 @@ struct TypeChecker<'a, 'tcx> { body: &'a Body<'tcx>, caller_body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, mir_phase: MirPhase, failures: Vec<(Location, String)>, } @@ -582,14 +582,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Variance::Covariant }; - crate::util::relate_types( - self.tcx, - self.body.typing_mode(self.tcx), - self.param_env, - variance, - src, - dest, - ) + crate::util::relate_types(self.tcx, self.typing_env, variance, src, dest) } /// Check that the given predicate definitely holds in the param-env of this MIR body. @@ -608,12 +601,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return true; } - let infcx = self.tcx.infer_ctxt().build(self.body.typing_mode(self.tcx)); + let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env); let ocx = ObligationCtxt::new(&infcx); ocx.register_obligation(Obligation::new( self.tcx, ObligationCause::dummy(), - self.param_env, + param_env, pred, )); ocx.select_all_or_error().is_empty() @@ -630,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if let Operand::Copy(place) = operand { let ty = place.ty(&self.body.local_decls, self.tcx).ty; - if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.typing_env.param_env) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}")); } } @@ -802,8 +795,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ProjectionElem::Subtype(ty) => { if !util::sub_types( self.tcx, - self.body.typing_mode(self.tcx), - self.param_env, + self.typing_env, ty, place_ref.ty(&self.body.local_decls, self.tcx).ty, ) { @@ -916,7 +908,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { assert!(adt_def.is_union()); assert_eq!(idx, FIRST_VARIANT); let dest_ty = self.tcx.normalize_erasing_regions( - self.param_env, + self.typing_env, adt_def.non_enum_variant().fields[field].ty(self.tcx, args), ); if let [field] = fields.raw.as_slice() { @@ -938,7 +930,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { for (src, dest) in std::iter::zip(fields, &variant.fields) { let dest_ty = self .tcx - .normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args)); + .normalize_erasing_regions(self.typing_env, dest.ty(self.tcx, args)); if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) { self.fail(location, "adt field has the wrong type"); } @@ -997,7 +989,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } // FIXME: check `Thin` instead of `Sized` - if !in_pointee.is_sized(self.tcx, self.param_env) { + if !in_pointee.is_sized(self.tcx, self.typing_env.param_env) { self.fail(location, "input pointer must be thin"); } } else { @@ -1012,7 +1004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) { self.fail(location, "slice metadata must be usize"); } - } else if pointee_ty.is_sized(self.tcx, self.param_env) { + } else if pointee_ty.is_sized(self.tcx, self.typing_env.param_env) { if metadata_ty != self.tcx.types.unit { self.fail(location, "metadata for pointer-to-thin must be unit"); } @@ -1301,8 +1293,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self .tcx - .normalize_erasing_regions(self.param_env, op_ty) - .is_sized(self.tcx, self.param_env) + .normalize_erasing_regions(self.typing_env, op_ty) + .is_sized(self.tcx, self.typing_env.param_env) { self.fail( location, @@ -1311,8 +1303,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } if !self .tcx - .normalize_erasing_regions(self.param_env, *target_type) - .is_sized(self.tcx, self.param_env) + .normalize_erasing_regions(self.typing_env, *target_type) + .is_sized(self.tcx, self.typing_env.param_env) { self.fail( location, @@ -1353,7 +1345,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { return; }; - current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty); + current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty); } ty::Adt(adt_def, args) => { let Some(field) = adt_def.variant(variant).fields.get(field) else { @@ -1362,7 +1354,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; let f_ty = field.ty(self.tcx, args); - current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty); + current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty); } _ => { self.fail( diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 322deb539cd..1b94c627f81 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -427,7 +427,7 @@ fn collect_items_rec<'tcx>( let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() }; // Nested statics have no type. if !nested { - let ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized()); visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items); } @@ -636,7 +636,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { trace!("monomorphize: self.instance={:?}", self.instance); self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value), ) } @@ -647,12 +647,11 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { constant: &mir::ConstOperand<'tcx>, ) -> Option> { let const_ = self.monomorphize(constant.const_); - let param_env = ty::ParamEnv::reveal_all(); // Evaluate the constant. This makes const eval failure a collection-time error (rather than // a codegen-time error). rustc stops after collection if there was an error, so this // ensures codegen never has to worry about failing consts. // (codegen relies on this and ICEs will happen if this is violated.) - match const_.eval(self.tcx, param_env, constant.span) { + match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) { Ok(v) => Some(v), Err(ErrorHandled::TooGeneric(..)) => span_bug!( constant.span, @@ -863,9 +862,20 @@ fn visit_fn_use<'tcx>( ) { if let ty::FnDef(def_id, args) = *ty.kind() { let instance = if is_direct_call { - ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, source) + ty::Instance::expect_resolve( + tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args, + source, + ) } else { - match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, args) { + match ty::Instance::resolve_for_fn_ptr( + tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args, + ) { Some(instance) => instance, _ => bug!("failed to resolve instance for {ty}"), } @@ -1024,12 +1034,12 @@ fn find_vtable_types_for_unsizing<'tcx>( target_ty: Ty<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>) { let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { - let param_env = ty::ParamEnv::reveal_all(); + let typing_env = ty::TypingEnv::fully_monomorphized(); let type_has_metadata = |ty: Ty<'tcx>| -> bool { - if ty.is_sized(tcx.tcx, param_env) { + if ty.is_sized(tcx.tcx, typing_env.param_env) { return false; } - let tail = tcx.struct_tail_for_codegen(ty, param_env); + let tail = tcx.struct_tail_for_codegen(ty, typing_env); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, @@ -1039,7 +1049,7 @@ fn find_vtable_types_for_unsizing<'tcx>( if type_has_metadata(inner_source) { (inner_source, inner_target) } else { - tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, param_env) + tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, typing_env) } }; @@ -1270,8 +1280,13 @@ fn visit_mentioned_item<'tcx>( match *item { MentionedItem::Fn(ty) => { if let ty::FnDef(def_id, args) = *ty.kind() { - let instance = - Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, span); + let instance = Instance::expect_resolve( + tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args, + span, + ); // `visit_instance_use` was written for "used" item collection but works just as well // for "mentioned" item collection. // We can set `is_direct_call`; that just means we'll skip a bunch of shims that anyway @@ -1487,13 +1502,13 @@ impl<'v> RootCollector<'_, 'v> { // regions must appear in the argument // listing. let main_ret_ty = self.tcx.normalize_erasing_regions( - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), main_ret_ty.no_bound_vars().unwrap(), ); let start_instance = Instance::expect_resolve( self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), start_def_id, self.tcx.mk_args(&[main_ret_ty.into()]), DUMMY_SP, @@ -1551,8 +1566,8 @@ fn create_mono_items_for_default_impls<'tcx>( return; } - let param_env = ty::ParamEnv::reveal_all(); - let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let trait_ref = tcx.normalize_erasing_regions(typing_env, trait_ref); let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id); for method in tcx.provided_trait_methods(trait_ref.def_id) { if overridden_methods.contains_key(&method.def_id) { @@ -1567,7 +1582,7 @@ fn create_mono_items_for_default_impls<'tcx>( // only has lifetime generic parameters. This is validated by calling // `own_requires_monomorphization` on both the impl and method. let args = trait_ref.args.extend_to(tcx, method.def_id, only_region_params); - let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args, DUMMY_SP); + let instance = ty::Instance::expect_resolve(tcx, typing_env, method.def_id, args, DUMMY_SP); let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP); if mono_item.node.is_instantiable(tcx) && tcx.should_codegen_locally(instance) { diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index eb576317678..0f08930fb4c 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -35,7 +35,9 @@ fn custom_coerce_unsize_info<'tcx>( [source_ty, target_ty], ); - match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) { + match tcx + .codegen_select_candidate(ty::TypingEnv::fully_monomorphized().as_query_input(trait_ref)) + { Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData { impl_def_id, .. diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 02b361456e4..30e634d8252 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -3,7 +3,7 @@ use rustc_hir::CRATE_HIR_ID; use rustc_middle::mir::{self, traversal}; use rustc_middle::ty::inherent::*; -use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt}; use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span, Symbol}; @@ -62,8 +62,9 @@ fn do_check_abi<'tcx>( /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments /// or return values for which the corresponding target feature is not enabled. fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { - let param_env = ParamEnv::reveal_all(); - let Ok(abi) = tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty()))) else { + let typing_env = ty::TypingEnv::fully_monomorphized(); + let Ok(abi) = tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) + else { // An error will be reported during codegen if we cannot determine the ABI of this // function. return; @@ -100,18 +101,18 @@ fn check_call_site_abi<'tcx>( // "Rust" ABI never passes arguments in vector registers. return; } - let param_env = ParamEnv::reveal_all(); + let typing_env = ty::TypingEnv::fully_monomorphized(); let callee_abi = match *callee.kind() { ty::FnPtr(..) => { - tcx.fn_abi_of_fn_ptr(param_env.and((callee.fn_sig(tcx), ty::List::empty()))) + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((callee.fn_sig(tcx), ty::List::empty()))) } ty::FnDef(def_id, args) => { // Intrinsics are handled separately by the compiler. if tcx.intrinsic(def_id).is_some() { return; } - let instance = ty::Instance::expect_resolve(tcx, param_env, def_id, args, DUMMY_SP); - tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty()))) + let instance = ty::Instance::expect_resolve(tcx, typing_env, def_id, args, DUMMY_SP); + tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) } _ => { panic!("Invalid function call"); @@ -151,7 +152,7 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m let callee_ty = func.ty(body, tcx); let callee_ty = instance.instantiate_mir_and_normalize_erasing_regions( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(callee_ty), ); check_call_site_abi(tcx, callee_ty, *fn_span, body.source.instance); diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index 7f04bdf46f1..438d49fd7fb 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -61,7 +61,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> { trace!("monomorphize: self.instance={:?}", self.instance); self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value), ) } @@ -128,7 +128,9 @@ impl<'tcx> MoveCheckVisitor<'tcx> { ) -> Option { let ty = operand.ty(self.body, self.tcx); let ty = self.monomorphize(ty); - let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else { + let Ok(layout) = + self.tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + else { return None; }; if layout.size.bytes_usize() > limit.0 { diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 84e08ea881d..7240cfce0f7 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -666,7 +666,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( // This is a method within an impl, find out what the self-type is: let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions( instance.args, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), tcx.type_of(impl_def_id), ); if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) { diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index 093a697beeb..deb4ab433bf 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -22,29 +22,29 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In let typeck_results = tcx.typeck(closure_def_id); if typeck_results.closure_size_eval.contains_key(&closure_def_id) { - let param_env = ty::ParamEnv::reveal_all(); + let typing_env = ty::TypingEnv::fully_monomorphized(); let ClosureSizeProfileData { before_feature_tys, after_feature_tys } = typeck_results.closure_size_eval[&closure_def_id]; let before_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, - param_env, + typing_env, ty::EarlyBinder::bind(before_feature_tys), ); let after_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, - param_env, + typing_env, ty::EarlyBinder::bind(after_feature_tys), ); let new_size = tcx - .layout_of(param_env.and(after_feature_tys)) + .layout_of(typing_env.as_query_input(after_feature_tys)) .map(|l| format!("{:?}", l.size.bytes())) .unwrap_or_else(|e| format!("Failed {e:?}")); let old_size = tcx - .layout_of(param_env.and(before_feature_tys)) + .layout_of(typing_env.as_query_input(before_feature_tys)) .map(|l| format!("{:?}", l.size.bytes())) .unwrap_or_else(|e| format!("Failed {e:?}")); diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index df4f0ffdd57..5f740590712 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -262,7 +262,11 @@ where return ecx.forced_ambiguity(MaybeCause::Ambiguity); } - if cx.layout_is_pointer_like(goal.param_env, goal.predicate.self_ty()) { + if cx.layout_is_pointer_like( + ecx.typing_mode(goal.param_env), + goal.param_env, + goal.predicate.self_ty(), + ) { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } else { diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index b1267562f7b..4db8584b884 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -59,9 +59,9 @@ fn unwrap_fn_abi<'tcx>( } fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { - let param_env = tcx.param_env(item_def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let args = GenericArgs::identity_for_item(tcx, item_def_id); - let instance = match Instance::try_resolve(tcx, param_env, item_def_id.into(), args) { + let instance = match Instance::try_resolve(tcx, typing_env, item_def_id.into(), args) { Ok(Some(instance)) => instance, Ok(None) => { // Not sure what to do here, but `LayoutError::Unknown` seems reasonable? @@ -75,7 +75,9 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut Err(_guaranteed) => return, }; let abi = unwrap_fn_abi( - tcx.fn_abi_of_instance(param_env.and((instance, /* extra_args */ ty::List::empty()))), + tcx.fn_abi_of_instance( + typing_env.as_query_input((instance, /* extra_args */ ty::List::empty())), + ), tcx, item_def_id, ); @@ -117,10 +119,10 @@ fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx, } fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { - let param_env = tcx.param_env(item_def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let span = tcx.def_span(item_def_id); - if !ensure_wf(tcx, param_env, ty, item_def_id, span) { + if !ensure_wf(tcx, typing_env, ty, item_def_id, span) { return; } let meta_items = attr.meta_item_list().unwrap_or_default(); @@ -134,10 +136,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut ); }; let abi = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr( - param_env - .and((sig_tys.with(*hdr), /* extra_args */ ty::List::empty())), - ), + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys.with(*hdr), + /* extra_args */ ty::List::empty(), + ))), tcx, item_def_id, ); @@ -165,10 +167,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut ); }; let abi1 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr( - param_env - .and((sig_tys1.with(*hdr1), /* extra_args */ ty::List::empty())), - ), + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys1.with(*hdr1), + /* extra_args */ ty::List::empty(), + ))), tcx, item_def_id, ); @@ -179,10 +181,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut ); }; let abi2 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr( - param_env - .and((sig_tys2.with(*hdr2), /* extra_args */ ty::List::empty())), - ), + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys2.with(*hdr2), + /* extra_args */ ty::List::empty(), + ))), tcx, item_def_id, ); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index b1db66fa52d..ecf8d34ad84 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -273,7 +273,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { data.get(expr.hir_id).expect("no offset_of_data for offset_of"); let body_did = self.typeck_results().hir_owner.to_def_id(); - let param_env = self.tcx.param_env(body_did); + let typing_env = ty::TypingEnv::non_body_analysis(self.tcx, body_did); let mut current_ty = container; @@ -285,13 +285,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { self.insert_def_id(field.did); let field_ty = field.ty(self.tcx, args); - current_ty = self.tcx.normalize_erasing_regions(param_env, field_ty); + current_ty = self.tcx.normalize_erasing_regions(typing_env, field_ty); } // we don't need to mark tuple fields as live, // but we may need to mark subfields ty::Tuple(tys) => { current_ty = - self.tcx.normalize_erasing_regions(param_env, tys[field.as_usize()]); + self.tcx.normalize_erasing_regions(typing_env, tys[field.as_usize()]); } _ => span_bug!(expr.span, "named field access on non-ADT"), } @@ -944,7 +944,10 @@ impl<'tcx> DeadVisitor<'tcx> { if is_positional && self .tcx - .layout_of(self.tcx.param_env(field.did).and(field_type)) + .layout_of( + ty::TypingEnv::non_body_analysis(self.tcx, field.did) + .as_query_input(field_type), + ) .map_or(true, |layout| layout.is_zst()) { return ShouldWarnAboutField::No; diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 986dce5b56d..bb90b5a1e31 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -2,10 +2,9 @@ use rustc_abi::{HasDataLayout, TargetDataLayout}; use rustc_ast::Attribute; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_middle::infer::canonical::ir::TypingMode; use rustc_middle::span_bug; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers}; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; @@ -39,11 +38,13 @@ pub fn test_layout(tcx: TyCtxt<'_>) { pub fn ensure_wf<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, def_id: LocalDefId, span: Span, ) -> bool { + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); let pred = ty::ClauseKind::WellFormed(ty.into()); let obligation = traits::Obligation::new( tcx, @@ -55,8 +56,6 @@ pub fn ensure_wf<'tcx>( param_env, pred, ); - let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); - let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); if !errors.is_empty() { @@ -69,13 +68,13 @@ pub fn ensure_wf<'tcx>( } fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { - let param_env = tcx.param_env(item_def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let span = tcx.def_span(item_def_id.to_def_id()); - if !ensure_wf(tcx, param_env, ty, item_def_id, span) { + if !ensure_wf(tcx, typing_env, ty, item_def_id, span) { return; } - match tcx.layout_of(param_env.and(ty)) { + match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(ty_layout) => { // Check out the `#[rustc_layout(..)]` attribute to tell what to dump. // The `..` are the names of fields to dump. @@ -107,19 +106,15 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { span, homogeneous_aggregate: format!( "{:?}", - ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env }) + ty_layout + .homogeneous_aggregate(&UnwrapLayoutCx { tcx, typing_env }) ), }); } sym::debug => { - let normalized_ty = format!( - "{}", - tcx.normalize_erasing_regions( - param_env.with_reveal_all_normalized(tcx), - ty, - ) - ); + let normalized_ty = + format!("{}", tcx.normalize_erasing_regions(typing_env, ty)); // FIXME: using the `Debug` impl here isn't ideal. let ty_layout = format!("{:#?}", *ty_layout); tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout }); @@ -140,7 +135,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { struct UnwrapLayoutCx<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> { @@ -155,9 +150,9 @@ impl<'tcx> HasTyCtxt<'tcx> for UnwrapLayoutCx<'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for UnwrapLayoutCx<'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - self.param_env +impl<'tcx> HasTypingEnv<'tcx> for UnwrapLayoutCx<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env } } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 366f7dd293c..c6c99852952 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1297,7 +1297,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode { let ty = self.typeck_results.expr_ty(expr); let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); - if ty.is_inhabited_from(self.ir.tcx, m, self.param_env) { + if ty.is_inhabited_from(self.ir.tcx, m, ty::TypingEnv::from_param_env(self.param_env)) { return succ; } match self.ir.lnks[succ] { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 9ea5023064c..936e5235c55 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -9,6 +9,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; +use rustc_middle::traits::Reveal; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef, @@ -108,6 +109,17 @@ impl<'p, 'tcx: 'p> fmt::Debug for RustcPatCtxt<'p, 'tcx> { } impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { + pub fn typing_mode(&self) -> ty::TypingMode<'tcx> { + debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing); + // FIXME(#132279): This is inside of a body. If we need to use the `param_env` + // and `typing_mode` we should reveal opaques defined by that body. + ty::TypingMode::non_body_analysis() + } + + pub fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env } + } + /// Type inference occasionally gives us opaque types in places where corresponding patterns /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited /// types, we use the corresponding concrete type if possible. @@ -139,7 +151,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { !ty.inhabited_predicate(self.tcx).apply_revealing_opaque( self.tcx, - self.param_env, + self.typing_env(), self.module, &|key| self.reveal_opaque_key(key), ) @@ -179,7 +191,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { variant.fields.iter().map(move |field| { let ty = field.ty(self.tcx, args); // `field.ty()` doesn't normalize after instantiating. - let ty = self.tcx.normalize_erasing_regions(self.param_env, ty); + let ty = self.tcx.normalize_erasing_regions(self.typing_env(), ty); let ty = self.reveal_opaque_ty(ty); (field, ty) }) @@ -369,7 +381,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { let is_inhabited = v .inhabited_predicate(cx.tcx, *def) .instantiate(cx.tcx, args) - .apply_revealing_opaque(cx.tcx, cx.param_env, cx.module, &|key| { + .apply_revealing_opaque(cx.tcx, cx.typing_env(), cx.module, &|key| { cx.reveal_opaque_key(key) }); // Variants that depend on a disabled unstable feature. @@ -430,7 +442,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { match bdy { PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity, PatRangeBoundary::Finite(value) => { - let bits = value.eval_bits(self.tcx, self.param_env); + let bits = value.eval_bits(self.tcx, self.typing_env()); match *ty.kind() { ty::Int(ity) => { let size = Integer::from_int_ty(&self.tcx, ity).size().bits(); @@ -539,7 +551,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { PatKind::Constant { value } => { match ty.kind() { ty::Bool => { - ctor = match value.try_eval_bool(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bool(cx.tcx, cx.typing_env()) { Some(b) => Bool(b), None => Opaque(OpaqueId::new()), }; @@ -547,7 +559,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Char | ty::Int(_) | ty::Uint(_) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { let x = match *ty.kind() { ty::Int(ity) => { @@ -564,7 +576,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Float(ty::FloatTy::F16) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { use rustc_apfloat::Float; let value = rustc_apfloat::ieee::Half::from_bits(bits); @@ -576,7 +588,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Float(ty::FloatTy::F32) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { use rustc_apfloat::Float; let value = rustc_apfloat::ieee::Single::from_bits(bits); @@ -588,7 +600,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Float(ty::FloatTy::F64) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { use rustc_apfloat::Float; let value = rustc_apfloat::ieee::Double::from_bits(bits); @@ -600,7 +612,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Float(ty::FloatTy::F128) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { use rustc_apfloat::Float; let value = rustc_apfloat::ieee::Quad::from_bits(bits); @@ -649,8 +661,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } ty::Float(fty) => { use rustc_apfloat::Float; - let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env)); - let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env)); + let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.typing_env())); + let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.typing_env())); match fty { ty::FloatTy::F16 => { use rustc_apfloat::ieee::Half; diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 0e6f905e7a1..2f4387e412d 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -133,7 +133,7 @@ fn encode_const<'tcx>( match ct_ty.kind() { ty::Int(ity) => { let bits = c - .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected monomorphic const in cfi"); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; if val < 0 { @@ -143,7 +143,7 @@ fn encode_const<'tcx>( } ty::Uint(_) => { let val = c - .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected monomorphic const in cfi"); let _ = write!(s, "{val}"); } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs index 01568a0f61c..562e288afaa 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs @@ -117,7 +117,9 @@ pub fn typeid_for_instance<'tcx>( .unwrap_or_else(|| bug!("typeid_for_instance: invalid option(s) `{:?}`", options.bits())); let instance = transform_instance(tcx, instance, transform_ty_options); let fn_abi = tcx - .fn_abi_of_instance(ty::ParamEnv::reveal_all().and((instance, ty::List::empty()))) + .fn_abi_of_instance( + ty::TypingEnv::fully_monomorphized().as_query_input((instance, ty::List::empty())), + ) .unwrap_or_else(|error| { bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}") }); diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index cba79a02f8b..9c01bd04353 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -136,18 +136,18 @@ impl<'tcx> TypeFolder> for TransformTy<'tcx> { return t; } let variant = adt_def.non_enum_variant(); - let param_env = self.tcx.param_env(variant.def_id); + let typing_env = ty::TypingEnv::post_analysis(self.tcx, variant.def_id); let field = variant.fields.iter().find(|field| { let ty = self.tcx.type_of(field.did).instantiate_identity(); let is_zst = self .tcx - .layout_of(param_env.and(ty)) + .layout_of(typing_env.as_query_input(ty)) .is_ok_and(|layout| layout.is_zst()); !is_zst }); if let Some(field) = field { let ty0 = self.tcx.normalize_erasing_regions( - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), field.ty(self.tcx, args), ); // Generalize any repr(transparent) user-defined type that is either a @@ -209,9 +209,9 @@ impl<'tcx> TypeFolder> for TransformTy<'tcx> { } } - ty::Alias(..) => { - self.fold_ty(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), t)) - } + ty::Alias(..) => self.fold_ty( + self.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), t), + ), ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => { bug!("fold_ty: unexpected `{:?}`", t.kind()); @@ -241,7 +241,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc let alias_ty = ty::AliasTy::new_from_args(tcx, assoc_ty.def_id, super_trait_ref.args); let resolved = tcx.normalize_erasing_regions( - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), alias_ty.to_ty(tcx), ); debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx)); @@ -376,7 +376,7 @@ pub(crate) fn transform_instance<'tcx>( // implementation will not. We need to walk back to the more general trait method let trait_ref = tcx.instantiate_and_normalize_erasing_regions( instance.args, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), trait_ref, ); let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref)); @@ -397,7 +397,7 @@ pub(crate) fn transform_instance<'tcx>( } else if tcx.is_closure_like(instance.def_id()) { // We're either a closure or a coroutine. Our goal is to find the trait we're defined on, // instantiate it, and take the type of its only method as our own. - let closure_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let closure_ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized()); let (trait_id, inputs) = match closure_ty.kind() { ty::Closure(..) => { let closure_args = instance.args.as_closure(); diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index 5c09879f60e..4e8db6096d4 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -41,7 +41,7 @@ pub(crate) fn try_new_allocation<'tcx>( let size = scalar.size(); let align = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) + .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .map_err(|e| e.stable(tables))? .align; let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi); @@ -53,7 +53,7 @@ pub(crate) fn try_new_allocation<'tcx>( ConstValue::ZeroSized => { let align = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::empty().and(ty)) + .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .map_err(|e| e.stable(tables))? .align; new_empty_allocation(align.abi) @@ -66,7 +66,7 @@ pub(crate) fn try_new_allocation<'tcx>( rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx); let layout = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) + .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .map_err(|e| e.stable(tables))?; let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi); @@ -90,7 +90,7 @@ pub(crate) fn try_new_allocation<'tcx>( let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory(); let ty_size = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) + .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .map_err(|e| e.stable(tables))? .size; allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables) diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs index cd91fc26c10..2eb0cea0e85 100644 --- a/compiler/rustc_smir/src/rustc_smir/builder.rs +++ b/compiler/rustc_smir/src/rustc_smir/builder.rs @@ -40,7 +40,7 @@ impl<'tcx> BodyBuilder<'tcx> { { let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions( tables.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(body), ); self.visit_body(&mut mono_body); @@ -60,7 +60,7 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> { location: mir::Location, ) { let const_ = constant.const_; - let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), constant.span) { + let val = match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) { Ok(v) => v, Err(mir::interpret::ErrorHandled::Reported(..)) => return, Err(mir::interpret::ErrorHandled::TooGeneric(..)) => { diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 3db65692af7..b19adf321c3 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -11,7 +11,7 @@ use std::iter; use rustc_abi::HasDataLayout; use rustc_hir::LangItem; use rustc_middle::ty::layout::{ - FnAbiOf, FnAbiOfHelpers, HasParamEnv, HasTyCtxt, LayoutOf, LayoutOfHelpers, + FnAbiOf, FnAbiOfHelpers, HasTyCtxt, HasTypingEnv, LayoutOf, LayoutOfHelpers, }; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::{ @@ -410,7 +410,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let tcx = tables.tcx; let mir_const = cnst.internal(&mut *tables, tcx); mir_const - .try_eval_target_usize(tables.tcx, ParamEnv::empty()) + .try_eval_target_usize(tables.tcx, ty::TypingEnv::fully_monomorphized()) .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) } fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result { @@ -428,7 +428,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let ty_internal = ty.internal(&mut *tables, tcx); let size = tables .tcx - .layout_of(ParamEnv::empty().and(ty_internal)) + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty_internal)) .map_err(|err| { Error::new(format!( "Cannot create a zero-sized constant for type `{ty_internal}`: {err}" @@ -469,7 +469,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); - let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size; + let size = tables + .tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + .unwrap() + .size; // We don't use Const::from_bits since it doesn't have any error checking. let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| { @@ -486,7 +490,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); - let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size; + let size = tables + .tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + .unwrap() + .size; // We don't use Const::from_bits since it doesn't have any error checking. let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| { @@ -523,7 +531,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let def_ty = tables.tcx.type_of(item.internal(&mut *tables, tcx)); tables .tcx - .instantiate_and_normalize_erasing_regions(args, ty::ParamEnv::reveal_all(), def_ty) + .instantiate_and_normalize_erasing_regions( + args, + ty::TypingEnv::fully_monomorphized(), + def_ty, + ) .stable(&mut *tables) } @@ -573,7 +585,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let mut tables = self.0.borrow_mut(); let instance = tables.instances[def]; assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation"); - instance.ty(tables.tcx, ParamEnv::reveal_all()).stable(&mut *tables) + instance.ty(tables.tcx, ty::TypingEnv::fully_monomorphized()).stable(&mut *tables) } fn instance_args(&self, def: InstanceDef) -> GenericArgs { @@ -642,7 +654,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let tcx = tables.tcx; let def_id = def.0.internal(&mut *tables, tcx); let args_ref = args.internal(&mut *tables, tcx); - match Instance::try_resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) { + match Instance::try_resolve( + tables.tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args_ref, + ) { Ok(Some(instance)) => Some(instance.stable(&mut *tables)), Ok(None) | Err(_) => None, } @@ -665,8 +682,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let tcx = tables.tcx; let def_id = def.0.internal(&mut *tables, tcx); let args_ref = args.internal(&mut *tables, tcx); - Instance::resolve_for_fn_ptr(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) - .stable(&mut *tables) + Instance::resolve_for_fn_ptr( + tables.tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args_ref, + ) + .stable(&mut *tables) } fn resolve_closure( @@ -827,9 +849,9 @@ impl<'tcx> LayoutOfHelpers<'tcx> for Tables<'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for Tables<'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - ty::ParamEnv::reveal_all() +impl<'tcx> HasTypingEnv<'tcx> for Tables<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 05b4ff327a9..94f51b87cff 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -26,7 +26,7 @@ pub(super) fn mangle<'tcx>( ) -> String { let def_id = instance.def_id(); // FIXME(eddyb) this should ideally not be needed. - let args = tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.args); + let args = tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), instance.args); let prefix = "_R"; let mut cx: SymbolMangler<'_> = SymbolMangler { @@ -237,15 +237,16 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { if !args.is_empty() { param_env = EarlyBinder::bind(param_env).instantiate(self.tcx, args); } + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; match &mut impl_trait_ref { Some(impl_trait_ref) => { assert_eq!(impl_trait_ref.self_ty(), self_ty); - *impl_trait_ref = self.tcx.normalize_erasing_regions(param_env, *impl_trait_ref); + *impl_trait_ref = self.tcx.normalize_erasing_regions(typing_env, *impl_trait_ref); self_ty = impl_trait_ref.self_ty(); } None => { - self_ty = self.tcx.normalize_erasing_regions(param_env, self_ty); + self_ty = self.tcx.normalize_erasing_regions(typing_env, self_ty); } } @@ -591,7 +592,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { ct_ty.print(self)?; let mut bits = ct - .try_to_bits(self.tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(self.tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected const to be monomorphic"); // Negative integer values are mangled using `n` as a "sign prefix". diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 808e6a50d85..9a7bdaa5b57 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -528,7 +528,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Find the method being called. let Ok(Some(instance)) = ty::Instance::try_resolve( tcx, - ctxt.param_env, + self.cx.typing_env(ctxt.param_env), ctxt.assoc_item.def_id, self.cx.resolve_vars_if_possible(ctxt.args), ) else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 1109b11d2a7..4e7d7b79ff4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2079,7 +2079,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { cand.trait_ref = self .tcx .try_normalize_erasing_regions( - self.tcx.param_env(cand.impl_def_id), + ty::TypingEnv::non_body_analysis(self.tcx, cand.impl_def_id), cand.trait_ref, ) .unwrap_or(cand.trait_ref); diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index c00246cfd7d..cf63f14fb93 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -513,7 +513,7 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: let method_def_id = method.def_id; let sig = tcx.fn_sig(method_def_id).instantiate_identity(); - let param_env = tcx.param_env(method_def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, method_def_id); let receiver_ty = tcx.liberate_late_bound_regions(method_def_id, sig.input(0)); if receiver_ty == tcx.types.self_param { @@ -523,7 +523,7 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: // e.g., `Rc<()>` let unit_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method_def_id); - match tcx.layout_of(param_env.and(unit_receiver_ty)).map(|l| l.backend_repr) { + match tcx.layout_of(typing_env.as_query_input(unit_receiver_ty)).map(|l| l.backend_repr) { Ok(BackendRepr::Scalar(..)) => (), abi => { tcx.dcx().span_delayed_bug( @@ -538,7 +538,7 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: // e.g., `Rc` let trait_object_receiver = receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method_def_id); - match tcx.layout_of(param_env.and(trait_object_receiver)).map(|l| l.backend_repr) { + match tcx.layout_of(typing_env.as_query_input(trait_object_receiver)).map(|l| l.backend_repr) { Ok(BackendRepr::ScalarPair(..)) => (), abi => { tcx.dcx().span_delayed_bug( diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index fe90066b4e7..c0603c06d42 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -611,11 +611,12 @@ pub fn try_evaluate_const<'tcx>( // // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All` // instead of having this logic here - let env = tcx.erase_regions(param_env).with_reveal_all_normalized(tcx); + let typing_env = + tcx.erase_regions(infcx.typing_env(param_env)).with_reveal_all_normalized(tcx); let erased_uv = tcx.erase_regions(uv); use rustc_middle::mir::interpret::ErrorHandled; - match tcx.const_eval_resolve_for_typeck(env, erased_uv, DUMMY_SP) { + match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, DUMMY_SP) { Ok(Ok(val)) => Ok(ty::Const::new_value( tcx, val, diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 4ff0910c9b9..1d3e8d43af7 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -144,7 +144,14 @@ pub fn compute_dropck_outlives_inner<'tcx>( result.overflows.len(), ty_stack.len() ); - dtorck_constraint_for_ty_inner(tcx, param_env, DUMMY_SP, depth, ty, &mut constraints)?; + dtorck_constraint_for_ty_inner( + tcx, + ocx.infcx.typing_env(param_env), + DUMMY_SP, + depth, + ty, + &mut constraints, + )?; // "outlives" represent types/regions that may be touched // by a destructor. @@ -196,10 +203,10 @@ pub fn compute_dropck_outlives_inner<'tcx>( /// Returns a set of constraints that needs to be satisfied in /// order for `ty` to be valid for destruction. -#[instrument(level = "debug", skip(tcx, param_env, span, constraints))] +#[instrument(level = "debug", skip(tcx, typing_env, span, constraints))] pub fn dtorck_constraint_for_ty_inner<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, span: Span, depth: usize, ty: Ty<'tcx>, @@ -234,20 +241,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( ty::Pat(ety, _) | ty::Array(ety, _) | ty::Slice(ety) => { // single-element containers, behave like their element rustc_data_structures::stack::ensure_sufficient_stack(|| { - dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, *ety, constraints) + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints) })?; } ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in tys.iter() { - dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, ty, constraints)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?; } Ok::<_, NoSolution>(()) })?, ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in args.as_closure().upvar_tys() { - dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, ty, constraints)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?; } Ok::<_, NoSolution>(()) })?, @@ -257,7 +264,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( for ty in args.as_coroutine_closure().upvar_tys() { dtorck_constraint_for_ty_inner( tcx, - param_env, + typing_env, span, depth + 1, ty, @@ -296,7 +303,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( // While we conservatively assume that all coroutines require drop // to avoid query cycles during MIR building, we can check the actual // witness during borrowck to avoid unnecessary liveness constraints. - if args.witness().needs_drop(tcx, tcx.erase_regions(param_env)) { + if args.witness().needs_drop(tcx, tcx.erase_regions(typing_env)) { constraints.outlives.extend(args.upvar_tys().iter().map(ty::GenericArg::from)); constraints.outlives.push(args.resume_ty().into()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index bf3f83ec827..1e0c487c4d4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1224,16 +1224,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The regions of a type don't affect the size of the type let tcx = self.tcx(); let self_ty = tcx.instantiate_bound_regions_with_erased(obligation.predicate.self_ty()); - // We should erase regions from both the param-env and type, since both - // may have infer regions. Specifically, after canonicalizing and instantiating, - // early bound regions turn into region vars in both the new and old solver. - let key = tcx.erase_regions(obligation.param_env.and(self_ty)); + // But if there are inference variables, we have to wait until it's resolved. - if key.has_non_region_infer() { + if (obligation.param_env, self_ty).has_non_region_infer() { candidates.ambiguous = true; return; } + // We should erase regions from both the param-env and type, since both + // may have infer regions. Specifically, after canonicalizing and instantiating, + // early bound regions turn into region vars in both the new and old solver. + let key = self.infcx.pseudo_canonicalize_query( + tcx.erase_regions(obligation.param_env), + tcx.erase_regions(self_ty), + ); if let Ok(layout) = tcx.layout_of(key) && layout.layout.is_pointer_like(&tcx.data_layout) { diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index bb56d6eaf54..8352d31d13a 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -276,8 +276,10 @@ fn vtable_entries<'tcx>( // The trait type may have higher-ranked lifetimes in it; // erase them if they appear, so that we get the type // at some particular call site. - let args = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), args); + let args = tcx.normalize_erasing_late_bound_regions( + ty::TypingEnv::fully_monomorphized(), + args, + ); // It's possible that the method relies on where-clauses that // do not hold for this particular set of type parameters. @@ -294,7 +296,7 @@ fn vtable_entries<'tcx>( let instance = ty::Instance::expect_resolve_for_vtable( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, DUMMY_SP, diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index d8c1c50d79a..57225df0819 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -6,7 +6,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::traits::CodegenObligationError; -use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{ ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, @@ -23,14 +23,15 @@ use tracing::debug; /// This also expects that `trait_ref` is fully normalized. pub(crate) fn codegen_select_candidate<'tcx>( tcx: TyCtxt<'tcx>, - (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>), + key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>>, ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { + let PseudoCanonicalInput { typing_env, value: trait_ref } = key; // We expect the input to be fully normalized. - debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref)); + debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(typing_env, trait_ref)); // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::from_param_env(param_env)); + let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env); let mut selcx = SelectionContext::new(&infcx); let obligation_cause = ObligationCause::dummy(); diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 4e5309eea28..51e4dbe81b3 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult}; -use rustc_middle::ty::{GenericArgs, TyCtxt}; +use rustc_middle::ty::{self, GenericArgs, TyCtxt}; use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::dropck_outlives::{ compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner, @@ -35,7 +35,7 @@ pub(crate) fn adt_dtorck_constraint( ) -> Result<&DropckConstraint<'_>, NoSolution> { let def = tcx.adt_def(def_id); let span = tcx.def_span(def_id); - let param_env = tcx.param_env(def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id); debug!("dtorck_constraint: {:?}", def); if def.is_manually_drop() { @@ -57,7 +57,7 @@ pub(crate) fn adt_dtorck_constraint( let mut result = DropckConstraint::empty(); for field in def.all_fields() { let fty = tcx.type_of(field.did).instantiate_identity(); - dtorck_constraint_for_ty_inner(tcx, param_env, span, 0, fty, &mut result)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result)?; } result.outlives.extend(tcx.destructor_constraints(def)); dedup_dtorck_constraint(&mut result); diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index d79059a39a1..68ff66bbce7 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -1,7 +1,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; use rustc_middle::traits::query::NoSolution; -use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Normalized, ObligationCause}; use tracing::debug; @@ -19,10 +19,10 @@ pub(crate) fn provide(p: &mut Providers) { fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + PartialEq + Copy>( tcx: TyCtxt<'tcx>, - goal: ParamEnvAnd<'tcx, T>, + goal: PseudoCanonicalInput<'tcx, T>, ) -> Result { - let ParamEnvAnd { param_env, value } = goal; - let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); + let PseudoCanonicalInput { typing_env, value } = goal; + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let cause = ObligationCause::dummy(); match infcx.at(&cause, param_env).query_normalize(value) { Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => { diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 9dabcea706f..023c8fad781 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -31,7 +31,7 @@ where #[cfg(feature = "rustc")] mod rustc { use rustc_middle::ty::layout::LayoutCx; - use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; + use rustc_middle::ty::{Ty, TyCtxt, TypingEnv}; use super::*; use crate::layout::tree::rustc::Err; @@ -43,7 +43,7 @@ mod rustc { pub(crate) fn answer(self) -> Answer< as QueryContext>::Ref> { let Self { src, dst, assume, context } = self; - let layout_cx = LayoutCx::new(context, ParamEnv::reveal_all()); + let layout_cx = LayoutCx::new(context, TypingEnv::fully_monomorphized()); // Convert `src` and `dst` from their rustc representations, to `Tree`-based // representations. diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 0184e93acf1..e2283383196 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -7,7 +7,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ - FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind, + FnAbiError, HasTyCtxt, HasTypingEnv, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind, }; use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt}; use rustc_session::config::OptLevel; @@ -26,11 +26,11 @@ pub(crate) fn provide(providers: &mut Providers) { // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), // or should go through `FnAbi` instead, to avoid losing any // adjustments `fn_abi_of_instance` might be performing. -#[tracing::instrument(level = "debug", skip(tcx, param_env))] +#[tracing::instrument(level = "debug", skip(tcx, typing_env))] fn fn_sig_for_fn_abi<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> ty::PolyFnSig<'tcx> { if let InstanceKind::ThreadLocalShim(..) = instance.def { return ty::Binder::dummy(tcx.mk_fn_sig( @@ -42,7 +42,7 @@ fn fn_sig_for_fn_abi<'tcx>( )); } - let ty = instance.ty(tcx, param_env); + let ty = instance.ty(tcx, typing_env); match *ty.kind() { ty::FnDef(..) => { // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering @@ -56,7 +56,10 @@ fn fn_sig_for_fn_abi<'tcx>( ty::FnDef(def_id, args) => tcx .fn_sig(def_id) .map_bound(|fn_sig| { - tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig) + tcx.normalize_erasing_regions( + ty::TypingEnv::non_body_analysis(tcx, def_id), + fn_sig, + ) }) .instantiate(tcx, args), _ => unreachable!(), @@ -329,27 +332,26 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv fn fn_abi_of_fn_ptr<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)>, + query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)>, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { - let (param_env, (sig, extra_args)) = query.into_parts(); - - let cx = LayoutCx::new(tcx, param_env); + let ty::PseudoCanonicalInput { typing_env, value: (sig, extra_args) } = query; + let cx = LayoutCx::new(tcx, typing_env); fn_abi_new_uncached(&cx, sig, extra_args, None, None, false) } fn fn_abi_of_instance<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)>, + query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)>, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { - let (param_env, (instance, extra_args)) = query.into_parts(); + let ty::PseudoCanonicalInput { typing_env, value: (instance, extra_args) } = query; - let sig = fn_sig_for_fn_abi(tcx, instance, param_env); + let sig = fn_sig_for_fn_abi(tcx, instance, typing_env); let caller_location = instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty()); fn_abi_new_uncached( - &LayoutCx::new(tcx, param_env), + &LayoutCx::new(tcx, typing_env), sig, extra_args, caller_location, @@ -395,7 +397,7 @@ fn adjust_for_rust_scalar<'tcx>( Some(kind) } else if let Some(pointee) = drop_target_pointee { // The argument to `drop_in_place` is semantically equivalent to a mutable reference. - Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.param_env()) }) + Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env.param_env) }) } else { None }; @@ -542,7 +544,7 @@ fn fn_abi_sanity_check<'tcx>( // With metadata. Must be unsized and not on the stack. assert!(arg.layout.is_unsized() && !on_stack); // Also, must not be `extern` type. - let tail = tcx.struct_tail_for_codegen(arg.layout.ty, cx.param_env()); + let tail = tcx.struct_tail_for_codegen(arg.layout.ty, cx.typing_env); if matches!(tail.kind(), ty::Foreign(..)) { // These types do not have metadata, so having `meta_attrs` is bogus. // Conceptually, unsized arguments must be copied around, which requires dynamically @@ -573,7 +575,7 @@ fn fn_abi_new_uncached<'tcx>( force_thin_self_ptr: bool, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { let tcx = cx.tcx(); - let sig = tcx.normalize_erasing_late_bound_regions(cx.param_env, sig); + let sig = tcx.normalize_erasing_late_bound_regions(cx.typing_env, sig); let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic); @@ -744,7 +746,7 @@ fn fn_abi_adjust_for_abi<'tcx>( #[tracing::instrument(level = "debug", skip(cx))] fn make_thin_self_ptr<'tcx>( - cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), + cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>), layout: TyAndLayout<'tcx>, ) -> TyAndLayout<'tcx> { let tcx = cx.tcx(); @@ -784,6 +786,6 @@ fn make_thin_self_ptr<'tcx>( // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result` // should always work because the type is always `*mut ()`. - ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap() + ..tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(unit_ptr_ty)).unwrap() } } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 1d8a0880760..84fc03a8f13 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -6,7 +6,9 @@ use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError}; use rustc_middle::ty::util::AsyncDropGlueMorphology; -use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{ + self, GenericArgsRef, Instance, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, +}; use rustc_span::sym; use rustc_trait_selection::traits; use rustc_type_ir::ClosureKind; @@ -17,18 +19,18 @@ use crate::errors::UnexpectedFnPtrAssociatedItem; fn resolve_instance_raw<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>, + key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)>, ) -> Result>, ErrorGuaranteed> { - let (param_env, (def_id, args)) = key.into_parts(); + let PseudoCanonicalInput { typing_env, value: (def_id, args) } = key; let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) { - debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); + debug!(" => associated item, attempting to find impl in typing_env {:#?}", typing_env); resolve_associated_item( tcx, def_id, - param_env, + typing_env, trait_def_id, - tcx.normalize_erasing_regions(param_env, args), + tcx.normalize_erasing_regions(typing_env, args), ) } else { let def = if tcx.intrinsic(def_id).is_some() { @@ -37,7 +39,7 @@ fn resolve_instance_raw<'tcx>( } else if tcx.is_lang_item(def_id, LangItem::DropInPlace) { let ty = args.type_at(0); - if ty.needs_drop(tcx, param_env) { + if ty.needs_drop(tcx, typing_env) { debug!(" => nontrivial drop glue"); match *ty.kind() { ty::Closure(..) @@ -93,15 +95,16 @@ fn resolve_instance_raw<'tcx>( fn resolve_associated_item<'tcx>( tcx: TyCtxt<'tcx>, trait_item_id: DefId, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, trait_id: DefId, rcvr_args: GenericArgsRef<'tcx>, ) -> Result>, ErrorGuaranteed> { - debug!(?trait_item_id, ?param_env, ?trait_id, ?rcvr_args, "resolve_associated_item"); + debug!(?trait_item_id, ?typing_env, ?trait_id, ?rcvr_args, "resolve_associated_item"); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_args); - let vtbl = match tcx.codegen_select_candidate((param_env, trait_ref)) { + let input = typing_env.as_query_input(trait_ref); + let vtbl = match tcx.codegen_select_candidate(input) { Ok(vtbl) => vtbl, Err( CodegenObligationError::Ambiguity @@ -116,7 +119,7 @@ fn resolve_associated_item<'tcx>( traits::ImplSource::UserDefined(impl_data) => { debug!( "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}", - param_env, trait_item_id, rcvr_args, impl_data + typing_env, trait_item_id, rcvr_args, impl_data ); assert!(!rcvr_args.has_infer()); assert!(!trait_ref.has_infer()); @@ -129,8 +132,9 @@ fn resolve_associated_item<'tcx>( .unwrap_or_else(|| { bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id); }); - let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); - let param_env = param_env.with_reveal_all_normalized(tcx); + + let typing_env = typing_env.with_reveal_all_normalized(tcx); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args); let args = translate_args( &infcx, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 63421dfdce6..02ee3f32915 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -19,7 +19,8 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ - self, AdtDef, CoroutineArgsExt, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, + self, AdtDef, CoroutineArgsExt, EarlyBinder, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt, + TypeVisitableExt, }; use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::sym; @@ -40,22 +41,22 @@ pub(crate) fn provide(providers: &mut Providers) { #[instrument(skip(tcx, query), level = "debug")] fn layout_of<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> Result, &'tcx LayoutError<'tcx>> { - let (param_env, ty) = query.into_parts(); + let PseudoCanonicalInput { typing_env, value: ty } = query; debug!(?ty); // Optimization: We convert to RevealAll and convert opaque types in the where bounds // to their hidden types. This reduces overall uncached invocations of `layout_of` and // is thus a small performance improvement. - let param_env = param_env.with_reveal_all_normalized(tcx); + let typing_env = typing_env.with_reveal_all_normalized(tcx); let unnormalized_ty = ty; // FIXME: We might want to have two different versions of `layout_of`: // One that can be called after typecheck has completed and can use // `normalize_erasing_regions` here and another one that can be called // before typecheck has completed and uses `try_normalize_erasing_regions`. - let ty = match tcx.try_normalize_erasing_regions(param_env, ty) { + let ty = match tcx.try_normalize_erasing_regions(typing_env, ty) { Ok(t) => t, Err(normalization_error) => { return Err(tcx @@ -66,10 +67,10 @@ fn layout_of<'tcx>( if ty != unnormalized_ty { // Ensure this layout is also cached for the normalized type. - return tcx.layout_of(param_env.and(ty)); + return tcx.layout_of(typing_env.as_query_input(ty)); } - let cx = LayoutCx::new(tcx, param_env); + let cx = LayoutCx::new(tcx, typing_env); let layout = layout_of_uncached(&cx, ty)?; let layout = TyAndLayout { ty, layout }; @@ -104,7 +105,7 @@ fn map_error<'tcx>( // This is sometimes not a compile error if there are trivially false where clauses. // See `tests/ui/layout/trivial-bounds-sized.rs` for an example. assert!(field.layout.is_unsized(), "invalid layout error {err:#?}"); - if !field.ty.is_sized(cx.tcx(), cx.param_env) { + if !field.ty.is_sized(cx.tcx(), cx.typing_env.param_env) { cx.tcx().dcx().delayed_bug(format!( "encountered unexpected unsized field in layout of {ty:?}: {field:#?}" )); @@ -152,7 +153,6 @@ fn layout_of_uncached<'tcx>( } let tcx = cx.tcx(); - let param_env = cx.param_env; let dl = cx.data_layout(); let scalar_unit = |value: Primitive| { let size = value.size(dl); @@ -178,12 +178,12 @@ fn layout_of_uncached<'tcx>( { if let Some(start) = start { scalar.valid_range_mut().start = start - .try_to_bits(tcx, param_env) + .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; } if let Some(end) = end { let mut end = end - .try_to_bits(tcx, param_env) + .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; if !include_end { end = end.wrapping_sub(1); @@ -235,8 +235,8 @@ fn layout_of_uncached<'tcx>( data_ptr.valid_range_mut().start = 1; } - let pointee = tcx.normalize_erasing_regions(param_env, pointee); - if pointee.is_sized(tcx, param_env) { + let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee); + if pointee.is_sized(tcx, cx.typing_env.param_env) { return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); } @@ -247,7 +247,7 @@ fn layout_of_uncached<'tcx>( { let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]); let metadata_ty = - match tcx.try_normalize_erasing_regions(param_env, pointee_metadata) { + match tcx.try_normalize_erasing_regions(cx.typing_env, pointee_metadata) { Ok(metadata_ty) => metadata_ty, Err(mut err) => { // Usually `::Metadata` can't be normalized because @@ -259,7 +259,7 @@ fn layout_of_uncached<'tcx>( // that is an alias, which is likely the cause of the normalization // error. match tcx.try_normalize_erasing_regions( - param_env, + cx.typing_env, tcx.struct_tail_raw(pointee, |ty| ty, || {}), ) { Ok(_) => {} @@ -283,7 +283,7 @@ fn layout_of_uncached<'tcx>( metadata } else { - let unsized_part = tcx.struct_tail_for_codegen(pointee, param_env); + let unsized_part = tcx.struct_tail_for_codegen(pointee, cx.typing_env); match unsized_part.kind() { ty::Foreign(..) => { @@ -316,7 +316,7 @@ fn layout_of_uncached<'tcx>( // Arrays and slices. ty::Array(element, mut count) => { if count.has_aliases() { - count = tcx.normalize_erasing_regions(param_env, count); + count = tcx.normalize_erasing_regions(cx.typing_env, count); if count.has_aliases() { return Err(error(cx, LayoutError::Unknown(ty))); } @@ -331,7 +331,7 @@ fn layout_of_uncached<'tcx>( .checked_mul(count, dl) .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?; - let abi = if count != 0 && ty.is_privately_uninhabited(tcx, param_env) { + let abi = if count != 0 && ty.is_privately_uninhabited(tcx, cx.typing_env) { BackendRepr::Uninhabited } else { BackendRepr::Memory { sized: true } @@ -620,7 +620,11 @@ fn layout_of_uncached<'tcx>( // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around. if cfg!(debug_assertions) && maybe_unsized - && def.non_enum_variant().tail().ty(tcx, args).is_sized(tcx, cx.param_env) + && def + .non_enum_variant() + .tail() + .ty(tcx, args) + .is_sized(tcx, cx.typing_env.param_env) { let mut variants = variants; let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap(); @@ -1024,7 +1028,7 @@ fn record_layout_for_printing<'tcx>(cx: &LayoutCx<'tcx>, layout: TyAndLayout<'tc // Ignore layouts that are done with non-empty environments or // non-monomorphic layouts, as the user only wants to see the stuff // resulting from the final codegen session. - if layout.ty.has_non_region_param() || !cx.param_env.caller_bounds().is_empty() { + if layout.ty.has_non_region_param() || !cx.typing_env.param_env.caller_bounds().is_empty() { return; } diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index fc05dd8256b..26ea81daf78 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -9,7 +9,7 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa let tcx = cx.tcx(); // Type-level uninhabitedness should always imply ABI uninhabitedness. - if layout.ty.is_privately_uninhabited(tcx, cx.param_env) { + if layout.ty.is_privately_uninhabited(tcx, cx.typing_env) { assert!(layout.is_uninhabited()); } diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 5fecbd310b7..d462dbd9416 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -14,14 +14,17 @@ use crate::errors::NeedsDropOverflow; type NeedsDropResult = Result; -fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn needs_drop_raw<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, +) -> bool { // If we don't know a type doesn't need drop, for example if it's a type // parameter without a `Copy` bound, then we conservatively return that it // needs drop. let adt_has_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant); - let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false) - .filter(filter_array_elements(tcx, query.param_env)) + let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_dtor, false) + .filter(filter_array_elements(tcx, query.typing_env)) .next() .is_some(); @@ -29,14 +32,17 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> res } -fn needs_async_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn needs_async_drop_raw<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, +) -> bool { // If we don't know a type doesn't need async drop, for example if it's a // type parameter without a `Copy` bound, then we conservatively return that // it needs async drop. let adt_has_async_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant); - let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_async_dtor, false) - .filter(filter_array_elements(tcx, query.param_env)) + let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_async_dtor, false) + .filter(filter_array_elements(tcx, query.typing_env)) .next() .is_some(); @@ -50,11 +56,11 @@ fn needs_async_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty /// logic that is easier to follow while not repeating any checks that may thus diverge. fn filter_array_elements<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> impl Fn(&Result, AlwaysRequiresDrop>) -> bool { move |ty| match ty { Ok(ty) => match *ty.kind() { - ty::Array(elem, _) => tcx.needs_drop_raw(param_env.and(elem)), + ty::Array(elem, _) => tcx.needs_drop_raw(typing_env.as_query_input(elem)), _ => true, }, Err(AlwaysRequiresDrop) => true, @@ -63,16 +69,16 @@ fn filter_array_elements<'tcx>( fn has_significant_drop_raw<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> bool { let res = drop_tys_helper( tcx, query.value, - query.param_env, + query.typing_env, adt_consider_insignificant_dtor(tcx), true, ) - .filter(filter_array_elements(tcx, query.param_env)) + .filter(filter_array_elements(tcx, query.typing_env)) .next() .is_some(); debug!("has_significant_drop_raw({:?}) = {:?}", query, res); @@ -81,7 +87,7 @@ fn has_significant_drop_raw<'tcx>( struct NeedsDropTypes<'tcx, F> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, // Whether to reveal coroutine witnesses, this is set // to `false` unless we compute `needs_drop` for a coroutine witness. reveal_coroutine_witnesses: bool, @@ -99,7 +105,7 @@ struct NeedsDropTypes<'tcx, F> { impl<'tcx, F> NeedsDropTypes<'tcx, F> { fn new( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, adt_components: F, ) -> Self { @@ -107,7 +113,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { seen_tys.insert(ty); Self { tcx, - param_env, + typing_env, reveal_coroutine_witnesses: false, seen_tys, query_ty: ty, @@ -180,7 +186,7 @@ where } } - _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), + _ if component.is_copy_modulo_regions(tcx, self.typing_env.param_env) => (), ty::Closure(_, args) => { for upvar in args.as_closure().upvar_tys() { @@ -204,7 +210,7 @@ where }; for required_ty in tys { let required = tcx - .try_normalize_erasing_regions(self.param_env, required_ty) + .try_normalize_erasing_regions(self.typing_env, required_ty) .unwrap_or(required_ty); queue_type(self, required); @@ -271,7 +277,7 @@ enum DtorType { fn drop_tys_helper<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, - param_env: rustc_middle::ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, adt_has_dtor: impl Fn(ty::AdtDef<'tcx>) -> Option, only_significant: bool, ) -> impl Iterator>> { @@ -337,7 +343,7 @@ fn drop_tys_helper<'tcx>( .map(|v| v.into_iter()) }; - NeedsDropTypes::new(tcx, param_env, ty, adt_components) + NeedsDropTypes::new(tcx, typing_env, ty, adt_components) } fn adt_consider_insignificant_dtor<'tcx>( @@ -375,7 +381,7 @@ fn adt_drop_tys<'tcx>( drop_tys_helper( tcx, tcx.type_of(def_id).instantiate_identity(), - tcx.param_env(def_id), + ty::TypingEnv::non_body_analysis(tcx, def_id), adt_has_dtor, false, ) @@ -392,7 +398,7 @@ fn adt_significant_drop_tys( drop_tys_helper( tcx, tcx.type_of(def_id).instantiate_identity(), // identical to `tcx.make_adt(def, identity_args)` - tcx.param_env(def_id), + ty::TypingEnv::non_body_analysis(tcx, def_id), adt_consider_insignificant_dtor(tcx), true, ) diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index aadb64f45d7..105ae76708b 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,6 +1,7 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::fold::TypeFoldable; use crate::inherent::*; @@ -20,6 +21,7 @@ use crate::{self as ty, Interner}; /// If neither of these functions are available, feel free to reach out to /// t-types for help. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum TypingMode { /// When checking whether impls overlap, we check whether any obligations diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 36ddddccfa2..f988f003c0f 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -13,7 +13,7 @@ use crate::lang_items::TraitSolverLangItem; use crate::relate::Relate; use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; -use crate::{self as ty, search_graph}; +use crate::{self as ty, TypingMode, search_graph}; pub trait Interner: Sized @@ -277,7 +277,12 @@ pub trait Interner: fn coroutine_is_gen(self, coroutine_def_id: Self::DefId) -> bool; fn coroutine_is_async_gen(self, coroutine_def_id: Self::DefId) -> bool; - fn layout_is_pointer_like(self, param_env: Self::ParamEnv, ty: Self::Ty) -> bool; + fn layout_is_pointer_like( + self, + typing_mode: TypingMode, + param_env: Self::ParamEnv, + ty: Self::Ty, + ) -> bool; type UnsizingParams: Deref>; fn unsizing_params_for_adt(self, adt_def_id: Self::DefId) -> Self::UnsizingParams; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9e11360cab4..f0787d286fd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1819,8 +1819,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T { // Only anon consts can implicitly capture params. // FIXME: is this correct behavior? - let param_env = cx.tcx.param_env(*def_id); - cx.tcx.normalize_erasing_regions(param_env, ct) + let typing_env = ty::TypingEnv::from_param_env(cx.tcx.param_env(*def_id)); + cx.tcx.normalize_erasing_regions(typing_env, ct) } else { ct }; @@ -2039,7 +2039,7 @@ pub(crate) fn clean_middle_ty<'tcx>( format!("{pat:?}").into_boxed_str(), ), ty::Array(ty, n) => { - let n = cx.tcx.normalize_erasing_regions(cx.param_env, n); + let n = cx.tcx.normalize_erasing_regions(cx.typing_env(), n); let n = print_const(cx, n); Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)), n.into()) } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index e3a0dbe1a7f..a10a6a92bf5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -772,8 +772,10 @@ impl Item { .find(|field| { let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did)); - tcx.layout_of(tcx.param_env(field.did).and(ty)) - .is_ok_and(|layout| !layout.is_1zst()) + tcx.layout_of( + ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty), + ) + .is_ok_and(|layout| !layout.is_1zst()) }) .map_or_else( || adt.all_fields().any(|field| field.vis.is_public()), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index e551e0170c6..d59b4e4081c 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -419,7 +419,10 @@ fn print_const_with_custom_print_scalar<'tcx>( } (mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => { let ty = ct.ty(); - let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size; + let size = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + .unwrap() + .size; let sign_extended_data = int.assert_scalar_int().to_int(size); let mut output = if with_underscores { format_integer_with_underscore_sep(&sign_extended_data.to_string()) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index d5f6bfe415d..a562a9eee71 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -19,7 +19,7 @@ use rustc_hir::{HirId, Path}; use rustc_interface::interface; use rustc_lint::{MissingDoc, late_lint_mod}; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks}; pub(crate) use rustc_session::config::{Options, UnstableOptions}; use rustc_session::{Session, lint}; @@ -88,6 +88,13 @@ impl<'tcx> DocContext<'tcx> { ret } + pub(crate) fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env: self.param_env, + } + } + /// Call the closure with the given parameters set as /// the generic parameters for a type alias' RHS. pub(crate) fn enter_alias( diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs index d85ba3a2b14..9317844956d 100644 --- a/src/librustdoc/html/render/type_layout.rs +++ b/src/librustdoc/html/render/type_layout.rs @@ -37,9 +37,9 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( } let tcx = cx.tcx(); - let param_env = tcx.param_env(ty_def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, ty_def_id); let ty = tcx.type_of(ty_def_id).instantiate_identity(); - let type_layout = tcx.layout_of(param_env.and(ty)); + let type_layout = tcx.layout_of(typing_env.as_query_input(ty)); let variants = if let Ok(type_layout) = type_layout && let Variants::Multiple { variants, tag, tag_encoding, .. } = @@ -71,7 +71,7 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( Vec::new() }; - let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| { + let type_layout_size = tcx.layout_of(typing_env.as_query_input(ty)).map(|layout| { let is_unsized = layout.is_unsized(); let is_uninhabited = layout.is_uninhabited(); let size = layout.size.bytes(); diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs index 0b82c0cd04c..00626a37ef8 100644 --- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { }, _ => return, } - && let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.param_env, fn_id, fn_gen_args) + && let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.typing_env(), fn_id, fn_gen_args) // TODO: This check currently bails if the local variable has no initializer. // That is overly conservative - the lint should fire even if there was no initializer, // but the variable has been initialized before `lhs` was evaluated. diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index 7d89195eeca..adac2f27ea8 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -62,7 +62,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - }) .is_some_and(|assoc_item| { let proj = Ty::new_projection(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, [])); - let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj); + let nty = cx.tcx.normalize_erasing_regions(cx.typing_env(), proj); nty.is_bool() }) diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index b167d7f2208..f864b7a5a8a 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -17,7 +17,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; @@ -755,7 +755,8 @@ impl TyCoercionStability { DefinedTy::Hir(ty) => Self::for_hir_ty(ty), DefinedTy::Mir(ty) => Self::for_mir_ty( cx.tcx, - ty.param_env, + // FIXME(#132279): convert `DefinedTy` to use `TypingEnv` instead. + ty::TypingEnv::from_param_env(ty.param_env), cx.tcx.instantiate_bound_regions_with_erased(ty.value), for_return, ), @@ -823,12 +824,12 @@ impl TyCoercionStability { } } - fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self { + fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self { let ty::Ref(_, mut ty, _) = *ty.kind() else { return Self::None; }; - ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty); + ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); loop { break match *ty.kind() { ty::Ref(_, ref_ty, _) => { diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs index 55afdbf22e1..617982f4da3 100644 --- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs +++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs @@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { sym::mem_forget if is_copy => return, sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => return, sym::mem_drop - if !(arg_ty.needs_drop(cx.tcx, cx.param_env) + if !(arg_ty.needs_drop(cx.tcx, cx.typing_env()) || is_must_use_func_call(cx, arg) || is_must_use_ty(cx, arg_ty) || drop_is_single_call_in_arm) => @@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span)) }, sym::mem_forget => { - if arg_ty.needs_drop(cx.tcx, cx.param_env) { + if arg_ty.needs_drop(cx.tcx, cx.typing_env()) { ( MEM_FORGET, Cow::Owned(format!( diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs index 25105817ad9..4bc6ad0798c 100644 --- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs @@ -70,7 +70,7 @@ fn check_sig(cx: &LateContext<'_>, name: Symbol, sig: &FnSig<'_>, fn_id: LocalDe .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(fn_id).instantiate_identity().output()); let ret_ty = cx .tcx - .try_normalize_erasing_regions(cx.param_env, ret_ty) + .try_normalize_erasing_regions(cx.typing_env(), ret_ty) .unwrap_or(ret_ty); if cx .tcx diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 314d0dfa26c..906da81b183 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -215,7 +215,7 @@ impl {self_ty_without_ref} {{ && implements_trait(cx, ret_ty, iterator_did, &[]) && let Some(iter_ty) = make_normalized_projection( cx.tcx, - cx.param_env, + cx.typing_env(), iterator_did, sym::Item, [ret_ty], diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index c5a2760234f..644365c9fe5 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, ParamEnv}; +use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, Span}; @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let ty::Array(element_type, cst) = ty.kind() && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx - .try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree() + .try_normalize_erasing_regions(cx.typing_env(), *cst).unwrap_or(*cst).try_to_valtree() && let element_count = element_count.to_target_usize(cx.tcx) && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size) diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs index 25f9be8b2d7..593704f206a 100644 --- a/src/tools/clippy/clippy_lints/src/large_futures.rs +++ b/src/tools/clippy/clippy_lints/src/large_futures.rs @@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture { && let ty = cx.typeck_results().expr_ty(arg) && let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() && implements_trait(cx, ty, future_trait_def_id, &[]) - && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) + && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) && let size = layout.layout.size() && size >= Size::from_bytes(self.future_size_threshold) { diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs index d2bdf194ada..5ed948c02bb 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs @@ -150,11 +150,11 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { } let mir = cx.tcx.optimized_mir(def_id); - let param_env = cx.tcx.param_env(def_id); + let typing_env = mir.typing_env(cx.tcx); let sizes_of_locals = || { mir.local_decls.iter().filter_map(|local| { - let layout = cx.tcx.layout_of(param_env.and(local.ty)).ok()?; + let layout = cx.tcx.layout_of(typing_env.as_query_input(local.ty)).ok()?; Some((local, layout.size.bytes())) }) }; diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index ee561ea85ed..48318682f33 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -151,7 +151,7 @@ fn is_ref_iterable<'tcx>( // Using by value won't consume anything if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::None, self_ty)); @@ -168,7 +168,7 @@ fn is_ref_iterable<'tcx>( }; if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::reborrow(mutbl), self_ty)); @@ -181,7 +181,7 @@ fn is_ref_iterable<'tcx>( // Attempt to borrow let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, self_ty, mutbl); if implements_trait(cx, self_ty, trait_id, &[]) - && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + && let Some(ty) = make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::borrow(mutbl), self_ty)); @@ -204,7 +204,7 @@ fn is_ref_iterable<'tcx>( && target != self_ty && implements_trait(cx, target, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::auto_reborrow(mutbl), target)) @@ -222,7 +222,7 @@ fn is_ref_iterable<'tcx>( if is_copy(cx, target) && implements_trait(cx, target, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::Deref, target)) @@ -240,7 +240,7 @@ fn is_ref_iterable<'tcx>( if self_ty.is_ref() && implements_trait(cx, target, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::auto_borrow(mutbl), target)) diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 9c41528e647..c00b9b368c4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -203,10 +203,10 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool { fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool { if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) && let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator) - && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.param_env, iter_trait, sym::Item, [iter_ty]) + && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.typing_env(), iter_trait, sym::Item, [iter_ty]) && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, sym::Item, [collect_ty]) && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions( - cx.param_env, + cx.typing_env(), Ty::new_projection_from_args(cx.tcx, into_iter_item_proj.def_id, into_iter_item_proj.args), ) { @@ -237,7 +237,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - ) && let args = cx.tcx.mk_args(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))]) && let proj_ty = Ty::new_projection_from_args(cx.tcx, iter_item.def_id, args) - && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty) + && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), proj_ty) { item_ty == EarlyBinder::bind(search_ty).instantiate(cx.tcx, cx.typeck_results().node_args(call_id)) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs index 062d1348555..7d01bdc2269 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, ) { let typeck_results = cx.typeck_results(); - let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results); + let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck_results); if let Some(id) = typeck_results.type_dependent_def_id(expr.hir_id) && (cx.tcx.is_diagnostic_item(sym::cmp_ord_min, id) || cx.tcx.is_diagnostic_item(sym::cmp_ord_max, id)) { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 82549413fa9..84ea3554a35 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -578,7 +578,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< if output_ty.contains(param_ty) { if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions( new_subst, - cx.param_env, + cx.typing_env(), bound_fn_sig.rebind(output_ty), ) { expr = parent_expr; diff --git a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs index d33021c2a7b..102fa7bc895 100644 --- a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs +++ b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs @@ -7,7 +7,7 @@ use super::ZST_OFFSET; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { if let ty::RawPtr(ty, _) = cx.typeck_results().expr_ty(recv).kind() - && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty)) + && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(*ty)) && layout.is_zst() { span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value"); diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index c1424b9f1dc..43b885fbd2c 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -421,7 +421,7 @@ fn replace_types<'tcx>( .expect_ty(cx.tcx) .to_ty(cx.tcx); - if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection) + if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), projection) && args[term_param_ty.index as usize] != GenericArg::from(projected_ty) { deque.push_back((*term_param_ty, projected_ty)); diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 5e20b406426..57fa4797c5e 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -278,23 +278,23 @@ impl<'tcx> NonCopyConst<'tcx> { fn is_value_unfrozen_expr(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { let args = cx.typeck_results().node_args(hir_id); - let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), DUMMY_SP); + let result = Self::const_eval_resolve(cx.tcx, cx.typing_env(), ty::UnevaluatedConst::new(def_id, args), DUMMY_SP); Self::is_value_unfrozen_raw(cx, result, ty) } pub fn const_eval_resolve( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ct: ty::UnevaluatedConst<'tcx>, span: Span, ) -> EvalToValTreeResult<'tcx> { - match ty::Instance::try_resolve(tcx, param_env, ct.def, ct.args) { + match ty::Instance::try_resolve(tcx, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: None, }; - tcx.const_eval_global_id_for_typeck(param_env, cid, span) + tcx.const_eval_global_id_for_typeck(typing_env.param_env, cid, span) }, Ok(None) => Err(ErrorHandled::TooGeneric(span)), Err(err) => Err(ErrorHandled::Reported(err.into(), span)), @@ -321,7 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { // Normalize assoc types because ones originated from generic params // bounded other traits could have their bound. - let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); + let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); if self.interior_mut.is_interior_mut_ty(cx, normalized) // When there's no default value, lint it only according to its type; // in other words, lint consts whose value *could* be unfrozen, not definitely is. @@ -361,12 +361,12 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { .trait_item_def_id && cx .tcx - .layout_of(cx.tcx.param_env(of_trait_def_id).and( + .layout_of(ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id).as_query_input( // Normalize assoc types because ones originated from generic params // bounded other traits could have their bound at the trait defs; // and, in that case, the definition is *not* generic. cx.tcx.normalize_erasing_regions( - cx.tcx.param_env(of_trait_def_id), + ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id), cx.tcx.type_of(of_assoc_item).instantiate_identity(), ), )) @@ -376,7 +376,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { // similar to unknown layouts. // e.g. `layout_of(...).is_err() || has_frozen_variant(...);` && let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity() - && let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty) + && let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty) && self.interior_mut.is_interior_mut_ty(cx, normalized) && Self::is_value_unfrozen_poly(cx, *body_id, normalized) { @@ -386,7 +386,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { ItemKind::Impl(Impl { of_trait: None, .. }) => { let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity(); // Normalize assoc types originated from generic params. - let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); + let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); if self.interior_mut.is_interior_mut_ty(cx, normalized) && Self::is_value_unfrozen_poly(cx, *body_id, normalized) diff --git a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs index 5d94cfab3b0..1a0bfd8b997 100644 --- a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs @@ -26,7 +26,7 @@ fn comparison_to_const<'tcx>( if let ExprKind::Binary(operator, left, right) = expr.kind && let Ok(cmp_op) = CmpOp::try_from(operator.node) { - let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck); + let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck); match (ecx.eval(left), ecx.eval(right)) { (Some(_), Some(_)) => None, (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))), diff --git a/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs index 24bfe2b050b..e3fc8d8fea7 100644 --- a/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs @@ -39,7 +39,7 @@ fn check_op<'tcx>( other: &Expr<'tcx>, parent: &Expr<'tcx>, ) { - if ConstEvalCtxt::with_env(cx.tcx, cx.param_env, tck).eval_simple(op) == Some(Constant::Int(0)) { + if ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), tck).eval_simple(op) == Some(Constant::Int(0)) { if different_types(tck, other, parent) { return; } diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs index ab5f91c1d67..8272d3643d4 100644 --- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs +++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs @@ -17,8 +17,7 @@ pub(crate) fn check<'tcx>( right: &'tcx Expr<'_>, ) { if (op == BinOpKind::Eq || op == BinOpKind::Ne) && is_float(cx, left) { - let typeck = cx.typeck_results(); - let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck); + let ecx = ConstEvalCtxt::new(cx); let left_is_local = match ecx.eval_with_source(left) { Some((c, s)) if !is_allowed(&c) => s.is_local(), Some(_) => return, diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index dc66fb28fa8..0ac818c21d9 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { }); } else if let Some(target_id) = cx.tcx.lang_items().deref_target() { if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( - cx.param_env, + cx.typing_env(), Ty::new_projection_from_args(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])), ) { if deref_ty == expr_ty { diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 1e0f6dff1ab..aeff31d02d2 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -391,7 +391,7 @@ fn check_final_expr<'tcx>( if let Some(inner) = inner { if for_each_unconsumed_temporary(cx, inner, |temporary_ty| { - if temporary_ty.has_significant_drop(cx.tcx, cx.param_env) + if temporary_ty.has_significant_drop(cx.tcx, cx.typing_env()) && temporary_ty .walk() .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static())) diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs index abd8363456d..1a5b958e6a6 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs @@ -154,7 +154,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> { let ty = self .cx .tcx - .try_normalize_erasing_regions(self.cx.param_env, ty) + .try_normalize_erasing_regions(self.cx.typing_env(), ty) .unwrap_or(ty); match self.type_cache.entry(ty) { Entry::Occupied(e) => return *e.get(), diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs index 52bb7c4bd68..50a1577b288 100644 --- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -58,7 +58,7 @@ fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: && let Some(last_field) = data.fields().last() && let field_ty = cx .tcx - .normalize_erasing_regions(cx.param_env, cx.tcx.type_of(last_field.def_id).instantiate_identity()) + .normalize_erasing_regions(cx.typing_env(), cx.tcx.type_of(last_field.def_id).instantiate_identity()) && let ty::Array(_, array_len) = *field_ty.kind() && let Some(0) = array_len.try_to_target_usize(cx.tcx) { diff --git a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs index ca9daf2d2a0..1209bd5b34f 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs @@ -88,8 +88,8 @@ pub(super) fn check<'tcx>( && is_normalizable(cx, cx.param_env, to_ty) // we only want to lint if the target type has a niche that is larger than the one of the source type // e.g. `u8` to `NonZero` should lint, but `NonZero` to `u8` should not - && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from_ty)) - && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to_ty)) + && let Ok(from_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(from_ty)) + && let Ok(to_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(to_ty)) && match (from_layout.largest_niche, to_layout.largest_niche) { (Some(from_niche), Some(to_niche)) => !range_fully_contained(from_niche.valid_range, to_niche.valid_range), (None, Some(_)) => true, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 3b32e4396b9..4dc1290e8b1 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -244,7 +244,7 @@ enum ReducedTy<'tcx> { /// Reduce structs containing a single non-zero sized field to it's contained type. fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> { loop { - ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty); + ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty); return match *ty.kind() { ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => { ReducedTy::TypeErasure { raw_ptr_only: false } @@ -297,8 +297,8 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> } fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) - && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) + if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) + && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) { layout.layout.size().bytes() == 0 } else { diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index e8ccd35b4da..5baa67b1f3e 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -4,10 +4,11 @@ use rustc_middle::ty::Ty; // check if the component types of the transmuted collection and the result have different ABI, // size or alignment pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { - if let Ok(from) = cx.tcx.try_normalize_erasing_regions(cx.param_env, from) - && let Ok(to) = cx.tcx.try_normalize_erasing_regions(cx.param_env, to) - && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from)) - && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to)) + let typing_env = cx.typing_env(); + if let Ok(from) = cx.tcx.try_normalize_erasing_regions(typing_env, from) + && let Ok(to) = cx.tcx.try_normalize_erasing_regions(typing_env, to) + && let Ok(from_layout) = cx.tcx.layout_of(typing_env.as_query_input(from)) + && let Ok(to_layout) = cx.tcx.layout_of(typing_env.as_query_input(to)) { from_layout.size != to_layout.size || from_layout.align.abi != to_layout.align.abi } else { diff --git a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs index cfa565cf803..ee9ef017253 100644 --- a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs +++ b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs @@ -46,7 +46,7 @@ impl LateLintPass<'_> for UninhabitedReferences { if let ExprKind::Unary(UnOp::Deref, _) = expr.kind { let ty = cx.typeck_results().expr_ty_adjusted(expr); - if ty.is_privately_uninhabited(cx.tcx, cx.param_env) { + if ty.is_privately_uninhabited(cx.tcx, cx.typing_env()) { span_lint( cx, UNINHABITED_REFERENCES, @@ -71,7 +71,7 @@ impl LateLintPass<'_> for UninhabitedReferences { } if let FnRetTy::Return(hir_ty) = fndecl.output && let TyKind::Ref(_, mut_ty) = hir_ty.kind - && lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.param_env) + && lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.typing_env()) { span_lint( cx, diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 24a02c7ef87..52c98646289 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -18,7 +18,7 @@ use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; use rustc_middle::mir::interpret::{Scalar, alloc_range}; -use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy}; +use rustc_middle::ty::{self, FloatTy, IntTy, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::def_id::DefId; use rustc_span::symbol::Ident; @@ -387,7 +387,7 @@ impl Ord for FullInt { /// See the module level documentation for some context. pub struct ConstEvalCtxt<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>, source: Cell, } @@ -398,17 +398,17 @@ impl<'tcx> ConstEvalCtxt<'tcx> { pub fn new(cx: &LateContext<'tcx>) -> Self { Self { tcx: cx.tcx, - param_env: cx.param_env, + typing_env: cx.typing_env(), typeck: cx.typeck_results(), source: Cell::new(ConstantSource::Local), } } /// Creates an evaluation context. - pub fn with_env(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self { + pub fn with_env(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self { Self { tcx, - param_env, + typing_env, typeck, source: Cell::new(ConstantSource::Local), } @@ -643,7 +643,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { let args = self.typeck.node_args(id); let result = self .tcx - .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) + .const_eval_resolve(self.typing_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) .ok() .map(|val| mir::Const::from_value(val, ty))?; f(self, result) diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index a2e97919d04..7f0363ac942 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -105,7 +105,7 @@ fn res_has_significant_drop(res: Res, cx: &LateContext<'_>, e: &Expr<'_>) -> boo { cx.typeck_results() .expr_ty(e) - .has_significant_drop(cx.tcx, cx.param_env) + .has_significant_drop(cx.tcx, cx.typing_env()) } else { false } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index c73ab4bfa68..ea866a78d87 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -297,8 +297,8 @@ impl HirEqInterExpr<'_, '_, '_> { if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results && typeck_lhs.expr_ty(left) == typeck_rhs.expr_ty(right) && let (Some(l), Some(r)) = ( - ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_lhs).eval_simple(left), - ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_rhs).eval_simple(right), + ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_lhs).eval_simple(left), + ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_rhs).eval_simple(right), ) && l == r { @@ -813,7 +813,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { #[expect(clippy::too_many_lines)] pub fn hash_expr(&mut self, e: &Expr<'_>) { let simple_const = self.maybe_typeck_results.and_then(|typeck_results| { - ConstEvalCtxt::with_env(self.cx.tcx, self.cx.param_env, typeck_results).eval_simple(e) + ConstEvalCtxt::with_env(self.cx.tcx, self.cx.typing_env(), typeck_results).eval_simple(e) }); // const hashing may result in the same hash as some unrelated node, so add a sort of diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 19316a90683..f28e5c9ed0e 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1631,7 +1631,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool } let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id); if let Some(Constant::Int(v)) = - ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(enclosing_body), cx.tcx.typeck(enclosing_body)).eval(e) + ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), cx.tcx.typeck(enclosing_body)).eval(e) { return value == v; } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 971f8eeb1b3..abadca71400 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -142,7 +142,7 @@ fn check_rvalue<'tcx>( // We cannot allow this for now. return Err((span, "unsizing casts are only allowed for references right now".into())); }; - let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, tcx.param_env(def_id)); + let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, ty::TypingEnv::post_analysis(tcx, def_id)); if let ty::Slice(_) | ty::Str = unsized_ty.kind() { check_operand(tcx, op, span, body, msrv)?; // Casting/coercing things to slices is fine. @@ -408,15 +408,17 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> return true; } + + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx)); // FIXME(const_trait_impl) constness let obligation = Obligation::new( tcx, ObligationCause::dummy_with_span(body.span), - ConstCx::new(tcx, body).param_env, + param_env, TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]), ); - let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx)); let mut selcx = SelectionContext::new(&infcx); let Some(impl_src) = selcx.select(&obligation).ok().flatten() else { return false; @@ -434,5 +436,5 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> ocx.select_all_or_error().is_empty() } - !ty.needs_drop(tcx, ConstCx::new(tcx, body).param_env) + !ty.needs_drop(tcx, ConstCx::new(tcx, body).typing_env) } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 770cd9c3786..2aad867dc0d 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -467,7 +467,7 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { if !seen.insert(ty) { return false; } - if !ty.has_significant_drop(cx.tcx, cx.param_env) { + if !ty.has_significant_drop(cx.tcx, cx.typing_env()) { false } // Check for std types which implement drop, but only for memory allocation. @@ -575,8 +575,9 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { /// Checks if a given type looks safe to be uninitialized. pub fn is_uninit_value_valid_for_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + let typing_env = cx.typing_env().with_reveal_all_normalized(cx.tcx); cx.tcx - .check_validity_requirement((ValidityRequirement::Uninit, cx.param_env.and(ty))) + .check_validity_requirement((ValidityRequirement::Uninit, typing_env.as_query_input(ty))) .unwrap_or_else(|_| is_uninit_value_valid_for_ty_fallback(cx, ty)) } @@ -725,7 +726,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option None, } }, - ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) { + ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) { Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty), _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)), }, @@ -1111,12 +1112,12 @@ pub fn make_projection<'tcx>( /// succeeds as well as everything checked by `make_projection`. pub fn make_normalized_projection<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, container_id: DefId, assoc_ty: Symbol, args: impl IntoIterator>>, ) -> Option> { - fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { + fn helper<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] if let Some((i, arg)) = ty .args @@ -1132,7 +1133,7 @@ pub fn make_normalized_projection<'tcx>( ); return None; } - match tcx.try_normalize_erasing_regions(param_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { + match tcx.try_normalize_erasing_regions(typing_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { Ok(ty) => Some(ty), Err(e) => { debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}"); @@ -1140,7 +1141,7 @@ pub fn make_normalized_projection<'tcx>( }, } } - helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, args)?) + helper(tcx, typing_env, make_projection(tcx, container_id, assoc_ty, args)?) } /// Helper to check if given type has inner mutability such as [`std::cell::Cell`] or @@ -1300,7 +1301,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl if let Some(deref_did) = cx.tcx.lang_items().deref_trait() && implements_trait(cx, ty, deref_did, &[]) { - make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty]) + make_normalized_projection(cx.tcx, cx.typing_env(), deref_did, sym::Target, [ty]) } else { None } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 16fcc26be33..745316913d9 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -12,7 +12,7 @@ use std::{cmp, mem}; use rustc_abi::{BackendRepr, Size}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Mutability, RetagKind}; -use rustc_middle::ty::layout::HasParamEnv; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use self::diagnostics::{RetagCause, RetagInfo}; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index f92150758dc..255a3578aae 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,6 +1,6 @@ use rustc_abi::{BackendRepr, Size}; use rustc_middle::mir::{Mutability, RetagKind}; -use rustc_middle::ty::layout::HasParamEnv; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use rustc_span::def_id::DefId; diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 1e56e104918..5ec497ef0ea 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -268,10 +268,14 @@ pub fn create_ecx<'tcx>( entry_type: EntryFnType, config: &MiriConfig, ) -> InterpResult<'tcx, InterpCx<'tcx, MiriMachine<'tcx>>> { - let param_env = ty::ParamEnv::reveal_all(); - let layout_cx = LayoutCx::new(tcx, param_env); - let mut ecx = - InterpCx::new(tcx, rustc_span::DUMMY_SP, param_env, MiriMachine::new(config, layout_cx)); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let layout_cx = LayoutCx::new(tcx, typing_env); + let mut ecx = InterpCx::new( + tcx, + rustc_span::DUMMY_SP, + typing_env.param_env, + MiriMachine::new(config, layout_cx) + ); // Some parts of initialization require a full `InterpCx`. MiriMachine::late_init(&mut ecx, config, { @@ -376,7 +380,7 @@ pub fn create_ecx<'tcx>( let main_ret_ty = main_ret_ty.no_bound_vars().unwrap(); let start_instance = ty::Instance::try_resolve( tcx, - ty::ParamEnv::reveal_all(), + typing_env, start_id, tcx.mk_args(&[ty::GenericArg::from(main_ret_ty)]), ) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 526030bef2e..4b34f1686a0 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -116,8 +116,8 @@ pub fn resolve_path<'tcx>( /// Gets the layout of a type at a path. #[track_caller] pub fn path_ty_layout<'tcx>(cx: &impl LayoutOf<'tcx>, path: &[&str]) -> TyAndLayout<'tcx> { - let ty = - resolve_path(cx.tcx(), path, Namespace::TypeNS).ty(cx.tcx(), ty::ParamEnv::reveal_all()); + let ty = resolve_path(cx.tcx(), path, Namespace::TypeNS) + .ty(cx.tcx(), cx.typing_env()); cx.layout_of(ty).to_result().ok().unwrap() } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 9668998aaa3..9c1951ec87a 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1127,7 +1127,9 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { }; let info = ecx.get_alloc_info(alloc_id); let def_ty = ecx.tcx.type_of(def_id).instantiate_identity(); - let extern_decl_layout = ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap(); + let extern_decl_layout = ecx.tcx.layout_of( + ecx.typing_env().as_query_input(def_ty) + ).unwrap(); if extern_decl_layout.size != info.size || extern_decl_layout.align.abi != info.align { throw_unsup_format!( "extern static `{link_name}` has been declared as `{krate}::{name}` \ -- cgit 1.4.1-3-g733a5 From 948cec0fad6d87f7f5993517f913aa0454b78674 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 19 Nov 2024 16:13:55 +0100 Subject: move `fn is_item_raw` to `TypingEnv` --- compiler/rustc_borrowck/src/type_check/mod.rs | 3 ++- compiler/rustc_codegen_cranelift/src/base.rs | 4 ++-- compiler/rustc_codegen_cranelift/src/common.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/type_.rs | 6 +++--- .../rustc_const_eval/src/check_consts/resolver.rs | 5 +---- compiler/rustc_const_eval/src/const_eval/machine.rs | 2 +- .../rustc_const_eval/src/interpret/eval_context.rs | 2 +- compiler/rustc_const_eval/src/interpret/intern.rs | 2 +- compiler/rustc_const_eval/src/interpret/memory.rs | 2 +- compiler/rustc_const_eval/src/interpret/validity.rs | 8 +++++--- compiler/rustc_hir_analysis/src/check/check.rs | 10 +++++----- compiler/rustc_hir_analysis/src/check/intrinsicck.rs | 17 +++++++++++------ compiler/rustc_hir_analysis/src/coherence/orphan.rs | 2 +- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 8 ++++++-- compiler/rustc_lint/src/builtin.rs | 14 ++++++-------- compiler/rustc_lint/src/drop_forget_useless.rs | 2 +- compiler/rustc_lint/src/reference_casting.rs | 2 +- compiler/rustc_lint/src/types.rs | 6 +++--- compiler/rustc_middle/src/mir/interpret/mod.rs | 6 +++--- compiler/rustc_middle/src/query/mod.rs | 8 ++++---- compiler/rustc_middle/src/ty/layout.rs | 14 +++++++------- compiler/rustc_middle/src/ty/util.rs | 20 ++++++++++++-------- .../rustc_mir_build/src/build/expr/as_operand.rs | 6 ++---- compiler/rustc_mir_build/src/build/mod.rs | 4 ++++ compiler/rustc_mir_build/src/check_unsafety.rs | 17 ++++++++--------- .../rustc_mir_build/src/thir/pattern/check_match.rs | 12 +++++++++++- .../rustc_mir_build/src/thir/pattern/const_to_pat.rs | 6 +++--- compiler/rustc_mir_transform/src/check_alignment.rs | 10 +++++----- compiler/rustc_mir_transform/src/copy_prop.rs | 4 ++-- .../rustc_mir_transform/src/deduce_param_attrs.rs | 2 +- compiler/rustc_mir_transform/src/gvn.rs | 19 +++++++++---------- compiler/rustc_mir_transform/src/inline.rs | 5 +---- .../rustc_mir_transform/src/known_panics_lint.rs | 2 +- compiler/rustc_mir_transform/src/ref_prop.rs | 4 ++-- compiler/rustc_mir_transform/src/ssa.rs | 6 +++--- compiler/rustc_mir_transform/src/validate.rs | 10 +++++----- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 4 +++- compiler/rustc_ty_utils/src/abi.rs | 2 +- compiler/rustc_ty_utils/src/common_traits.rs | 17 ++++++++--------- compiler/rustc_ty_utils/src/layout.rs | 14 +++++--------- compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- src/librustdoc/clean/auto_trait.rs | 2 +- .../clippy/clippy_lints/src/casts/ptr_as_ptr.rs | 2 +- src/tools/clippy/clippy_lints/src/dereference.rs | 2 +- .../clippy/clippy_lints/src/functions/must_use.rs | 2 +- src/tools/clippy/clippy_lints/src/let_if_seq.rs | 2 +- .../clippy_lints/src/methods/manual_inspect.rs | 6 +++--- src/tools/clippy/clippy_lints/src/mut_mut.rs | 2 +- .../clippy_lints/src/needless_pass_by_value.rs | 2 +- src/tools/clippy/clippy_lints/src/question_mark.rs | 2 +- .../src/transmute/transmute_ptr_to_ptr.rs | 2 +- .../src/transmute/transmute_undefined_repr.rs | 4 ++-- .../clippy_lints/src/types/redundant_allocation.rs | 2 +- src/tools/clippy/clippy_lints/src/types/vec_box.rs | 2 +- .../clippy_lints/src/unnecessary_box_returns.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 2 +- .../miri/src/borrow_tracker/stacked_borrows/mod.rs | 7 +++---- .../miri/src/borrow_tracker/tree_borrows/mod.rs | 11 +++++------ 60 files changed, 181 insertions(+), 168 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 58a23b9e558..c6b34d5bf1d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1727,7 +1727,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // `Sized` bound in no way depends on precise regions, so this // shouldn't affect `is_sized`. let erased_ty = tcx.erase_regions(ty); - if !erased_ty.is_sized(tcx, self.infcx.param_env) { + // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here. + if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) { // in current MIR construction, all non-control-flow rvalue // expressions evaluate through `as_temp` or `into` a return // slot or local, so to find all unsized rvalues it is enough diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 1b91d251bfd..77ee9773940 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -11,7 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::InlineAsmMacro; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv}; use rustc_middle::ty::print::with_no_trimmed_paths; use crate::constant::ConstantCx; @@ -841,7 +841,7 @@ fn codegen_stmt<'tcx>( lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); } Rvalue::NullaryOp(ref null_op, ty) => { - assert!(lval.layout().ty.is_sized(fx.tcx, ty::ParamEnv::reveal_all())); + assert!(lval.layout().ty.is_sized(fx.tcx, fx.typing_env())); let layout = fx.layout_of(fx.monomorphize(ty)); let val = match null_op { NullOp::SizeOf => layout.size.bytes(), diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index add081bc795..c663fa32965 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -103,7 +103,7 @@ fn clif_pair_type_from_ty<'tcx>( /// Is a pointer to this type a wide ptr? pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - if ty.is_sized(tcx, ty::ParamEnv::reveal_all()) { + if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) { return false; } diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 3810c609fd4..6292d321f6b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -78,15 +78,15 @@ pub trait DerivedTypeCodegenMethods<'tcx>: } fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { - ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all()) + ty.is_sized(self.tcx(), self.typing_env()) } fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all()) + ty.is_freeze(self.tcx(), self.typing_env()) } fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { - if ty.is_sized(self.tcx(), self.param_env()) { + if ty.is_sized(self.tcx(), self.typing_env()) { return false; } diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index 03624a2ce50..0f9a460ca1b 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -120,10 +120,7 @@ where /// /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool { - !place - .ty(self.ccx.body, self.ccx.tcx) - .ty - .is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env) + !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.typing_env) } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 19c3195aaa4..347b1557d87 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -667,7 +667,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { .is_some_and(|p| !p.immutable()) { // That next check is expensive, that's why we have all the guards above. - let is_immutable = ty.is_freeze(*ecx.tcx, ecx.param_env); + let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env()); let place = ecx.ref_to_mplace(val)?; let new_place = if is_immutable { place.map_provenance(CtfeProvenance::as_immutable) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 4f413c84615..31ce1600ce7 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -250,7 +250,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { #[inline] pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(*self.tcx, self.param_env) + ty.is_freeze(*self.tcx, self.typing_env()) } pub fn load_mir( diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 7a1b92601a4..2d695688ae5 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -165,7 +165,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval InternKind::Static(Mutability::Not) => { ( // Outermost allocation is mutable if `!Freeze`. - if ret.layout.ty.is_freeze(*ecx.tcx, ecx.param_env) { + if ret.layout.ty.is_freeze(*ecx.tcx, ecx.typing_env()) { Mutability::Not } else { Mutability::Mut diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 07566e9fda2..9bae9c4b310 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -860,7 +860,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // # Global allocations if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) { let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env()); - let mutbl = global_alloc.mutability(*self.tcx, self.param_env); + let mutbl = global_alloc.mutability(*self.tcx, self.typing_env()); let kind = match global_alloc { GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData, GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"), diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 005b430bc8a..9ff24a01689 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -619,7 +619,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { }; // Determine what it actually points to. let alloc_actual_mutbl = - global_alloc.mutability(*self.ecx.tcx, self.ecx.param_env); + global_alloc.mutability(*self.ecx.tcx, self.ecx.typing_env()); // Mutable pointer to immutable memory is no good. if ptr_expected_mutbl == Mutability::Mut && alloc_actual_mutbl == Mutability::Not @@ -848,7 +848,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) { let tcx = *self.ecx.tcx; // Everything must be already interned. - let mutbl = tcx.global_alloc(alloc_id).mutability(tcx, self.ecx.param_env); + let mutbl = tcx.global_alloc(alloc_id).mutability(tcx, self.ecx.typing_env()); if let Some((_, alloc)) = self.ecx.memory.alloc_map.get(alloc_id) { assert_eq!(alloc.mutability, mutbl); } @@ -1085,7 +1085,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, ) -> InterpResult<'tcx> { // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory. if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) { - if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) { + if !val.layout.is_zst() + && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env()) + { if !self.in_mutable_memory(val) { throw_validation_failure!(self.path, UnsafeCellInImmutable); } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index cf8c81c0b08..aa9d303cacb 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -90,24 +90,24 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b fn allowed_union_field<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { // We don't just accept all !needs_drop fields, due to semver concerns. match ty.kind() { ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check) ty::Tuple(tys) => { // allow tuples of allowed types - tys.iter().all(|ty| allowed_union_field(ty, tcx, param_env)) + tys.iter().all(|ty| allowed_union_field(ty, tcx, typing_env)) } ty::Array(elem, _len) => { // Like `Copy`, we do *not* special-case length 0. - allowed_union_field(*elem, tcx, param_env) + allowed_union_field(*elem, tcx, typing_env) } _ => { // Fallback case: allow `ManuallyDrop` and things that are `Copy`, // also no need to report an error if the type is unresolved. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) - || ty.is_copy_modulo_regions(tcx, param_env) + || ty.is_copy_modulo_regions(tcx, typing_env) || ty.references_error() } } @@ -121,7 +121,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b continue; }; - if !allowed_union_field(field_ty, tcx, typing_env.param_env) { + if !allowed_union_field(field_ty, tcx, typing_env) { let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { // We are currently checking the type this field came from, so it must be local. Some(Node::Field(field)) => (field.span, field.ty.span), diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index e95669c9d40..dfddf93a5c2 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -15,7 +15,7 @@ use rustc_target::asm::{ pub struct InlineAsmCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, get_operand_ty: Box) -> Ty<'tcx> + 'a>, } @@ -23,24 +23,29 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self { InlineAsmCtxt { tcx, - param_env: ty::ParamEnv::empty(), + typing_env: ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env: ty::ParamEnv::empty(), + }, get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), } } + // FIXME(#132279): This likely causes us to incorrectly handle opaque types in their + // defining scope. pub fn new_in_fn( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, get_operand_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a, ) -> Self { - InlineAsmCtxt { tcx, param_env, get_operand_ty: Box::new(get_operand_ty) } + InlineAsmCtxt { tcx, typing_env, get_operand_ty: Box::new(get_operand_ty) } } // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()` fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool { // Type still may have region variables, but `Sized` does not depend // on those, so just erase them before querying. - if ty.is_sized(self.tcx, self.param_env) { + if ty.is_sized(self.tcx, self.typing_env) { return true; } if let ty::Foreign(..) = ty.kind() { @@ -171,7 +176,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. - if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { let msg = "arguments for inline assembly must be copyable"; self.tcx .dcx() diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 8a1a887766c..eca85c22a40 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -172,7 +172,7 @@ pub(crate) fn orphan_check_impl( // impl AutoTrait for T {} // impl AutoTrait for T {} ty::Param(..) => ( - if self_ty.is_sized(tcx, tcx.param_env(impl_def_id)) { + if self_ty.is_sized(tcx, ty::TypingEnv::non_body_analysis(tcx, impl_def_id)) { LocalImpl::Allow } else { LocalImpl::Disallow { problematic_kind: "generic type" } diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 59bef8315d8..2a00530c434 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -228,7 +228,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { } fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(self.0.tcx, self.0.param_env) + ty.is_copy_modulo_regions(self.0.tcx, self.0.typing_env()) } fn body_owner_def_id(&self) -> LocalDefId { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 50d1322eba6..961526831fb 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -105,8 +105,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.erase_regions(ty) } }; - InlineAsmCtxt::new_in_fn(self.tcx, self.param_env, get_operand_ty) - .check_asm(asm, enclosing_id); + InlineAsmCtxt::new_in_fn( + self.tcx, + self.infcx.typing_env(self.param_env), + get_operand_ty, + ) + .check_asm(asm, enclosing_id); } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index f6366ec3b80..bda982a3675 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -32,7 +32,7 @@ use rustc_middle::bug; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, VariantDef}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; use rustc_session::lint::FutureIncompatibilityReason; // hardwired lints from rustc_lint_defs pub use rustc_session::lint::builtin::*; @@ -586,10 +586,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } } - if ty.is_copy_modulo_regions(cx.tcx, cx.param_env) { + if ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) { return; } - if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.param_env) { + if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.typing_env()) { return; } if def.is_variant_list_non_exhaustive() @@ -637,8 +637,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { fn type_implements_negative_copy_modulo_regions<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, None), [ty]); let pred = ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Negative }; let obligation = traits::Obligation { @@ -647,10 +648,7 @@ fn type_implements_negative_copy_modulo_regions<'tcx>( recursion_depth: 0, predicate: pred.upcast(tcx), }; - - tcx.infer_ctxt() - .build(TypingMode::non_body_analysis()) - .predicate_must_hold_modulo_regions(&obligation) + infcx.predicate_must_hold_modulo_regions(&obligation) } declare_lint! { diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 364c6fd488a..8fe86738658 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id) { let arg_ty = cx.typeck_results().expr_ty(arg); - let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env); + let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); let let_underscore_ignore_sugg = || { if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 45d97403d60..7c6656f91c9 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -168,7 +168,7 @@ fn is_cast_from_ref_to_mut_ptr<'tcx>( // Except on the presence of non concrete skeleton types (ie generics) // since there is no way to make it safe for arbitrary types. let inner_ty_has_interior_mutability = - !inner_ty.is_freeze(cx.tcx, cx.param_env) && inner_ty.has_concrete_skeleton(); + !inner_ty.is_freeze(cx.tcx, cx.typing_env()) && inner_ty.has_concrete_skeleton(); (!need_check_freeze || !inner_ty_has_interior_mutability) .then_some(inner_ty_has_interior_mutability) } else { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 2e6cb993842..b1d7d4ab689 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -292,7 +292,7 @@ fn lint_wide_pointer<'tcx>( _ => return None, }; - (!ty.is_sized(cx.tcx, cx.param_env)) + (!ty.is_sized(cx.tcx, cx.typing_env())) .then(|| (refs, modifiers, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))) }; @@ -904,7 +904,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let Some(boxed) = ty.boxed_ty() && matches!(self.mode, CItemKind::Definition) { - if boxed.is_sized(tcx, self.cx.param_env) { + if boxed.is_sized(tcx, self.cx.typing_env()) { return FfiSafe; } else { return FfiUnsafe { @@ -1069,7 +1069,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::RawPtr(ty, _) | ty::Ref(_, ty, _) if { matches!(self.mode, CItemKind::Definition) - && ty.is_sized(self.cx.tcx, self.cx.param_env) + && ty.is_sized(self.cx.tcx, self.cx.typing_env()) } => { FfiSafe diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index c4b0e6e39cc..8d73c9e76de 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -46,7 +46,7 @@ pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance}; pub use self::value::Scalar; use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; +use crate::ty::{self, Instance, Ty, TyCtxt}; /// Uniquely identifies one of the following: /// - A constant @@ -312,7 +312,7 @@ impl<'tcx> GlobalAlloc<'tcx> { } } - pub fn mutability(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Mutability { + pub fn mutability(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Mutability { // Let's see what kind of memory we are. match self { GlobalAlloc::Static(did) => { @@ -334,7 +334,7 @@ impl<'tcx> GlobalAlloc<'tcx> { .type_of(did) .no_bound_vars() .expect("statics should not have generic parameters") - .is_freeze(tcx, param_env) => + .is_freeze(tcx, typing_env) => { Mutability::Mut } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 684d5b6c2a7..b8291e8a352 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1390,19 +1390,19 @@ rustc_queries! { /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, /// `ty.is_copy()`, etc, since that will prune the environment where possible. - query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query is_copy_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Copy`", env.value } } /// Query backing `Ty::is_sized`. - query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query is_sized_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Sized`", env.value } } /// Query backing `Ty::is_freeze`. - query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query is_freeze_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } } /// Query backing `Ty::is_unpin`. - query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query is_unpin_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Unpin`", env.value } } /// Query backing `Ty::needs_drop`. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8625a8dcb2a..fc29b438d3a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1002,12 +1002,12 @@ where // attributes in LLVM have compile-time cost even in unoptimized builds). let optimize = tcx.sess.opts.optimize != OptLevel::No; let kind = match mt { - hir::Mutability::Not => PointerKind::SharedRef { - frozen: optimize && ty.is_freeze(tcx, typing_env.param_env), - }, - hir::Mutability::Mut => PointerKind::MutableRef { - unpin: optimize && ty.is_unpin(tcx, typing_env.param_env), - }, + hir::Mutability::Not => { + PointerKind::SharedRef { frozen: optimize && ty.is_freeze(tcx, typing_env) } + } + hir::Mutability::Mut => { + PointerKind::MutableRef { unpin: optimize && ty.is_unpin(tcx, typing_env) } + } }; tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo { @@ -1100,7 +1100,7 @@ where debug_assert!(pointee.safe.is_none()); let optimize = tcx.sess.opts.optimize != OptLevel::No; pointee.safe = Some(PointerKind::Box { - unpin: optimize && boxed_ty.is_unpin(tcx, typing_env.param_env), + unpin: optimize && boxed_ty.is_unpin(tcx, typing_env), global: this.ty.is_box_global(tcx), }); } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 703a7826b7a..20c3f84bb4d 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1180,8 +1180,12 @@ impl<'tcx> Ty<'tcx> { /// does copies even when the type actually doesn't satisfy the /// full requirements for the `Copy` trait (cc #29149) -- this /// winds up being reported as an error during NLL borrow check. - pub fn is_copy_modulo_regions(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(param_env.and(self)) + pub fn is_copy_modulo_regions( + self, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> bool { + self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(typing_env.as_query_input(self)) } /// Checks whether values of this type `T` have a size known at @@ -1190,8 +1194,8 @@ impl<'tcx> Ty<'tcx> { /// over-approximation in generic contexts, where one can have /// strange rules like `>::Bar: Sized` that /// actually carry lifetime requirements. - pub fn is_sized(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_sized(tcx) || tcx.is_sized_raw(param_env.and(self)) + pub fn is_sized(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { + self.is_trivially_sized(tcx) || tcx.is_sized_raw(typing_env.as_query_input(self)) } /// Checks whether values of this type `T` implement the `Freeze` @@ -1201,8 +1205,8 @@ impl<'tcx> Ty<'tcx> { /// optimization as well as the rules around static values. Note /// that the `Freeze` trait is not exposed to end users and is /// effectively an implementation detail. - pub fn is_freeze(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_freeze() || tcx.is_freeze_raw(param_env.and(self)) + pub fn is_freeze(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { + self.is_trivially_freeze() || tcx.is_freeze_raw(typing_env.as_query_input(self)) } /// Fast path helper for testing if a type is `Freeze`. @@ -1241,8 +1245,8 @@ impl<'tcx> Ty<'tcx> { } /// Checks whether values of this type `T` implement the `Unpin` trait. - pub fn is_unpin(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_unpin() || tcx.is_unpin_raw(param_env.and(self)) + pub fn is_unpin(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { + self.is_trivially_unpin() || tcx.is_unpin_raw(typing_env.as_query_input(self)) } /// Fast path helper for testing if a type is `Unpin`. diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index aad7d54833b..159959d4f1f 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -165,11 +165,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if tcx.features().unsized_fn_params() { let ty = expr.ty; - let param_env = this.param_env; - - if !ty.is_sized(tcx, param_env) { + if !ty.is_sized(tcx, this.typing_env()) { // !sized means !copy, so this is an unsized move - assert!(!ty.is_copy_modulo_regions(tcx, param_env)); + assert!(!ty.is_copy_modulo_regions(tcx, this.typing_env())); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index cf8dc597b7b..3317f3b7f8a 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -148,6 +148,10 @@ struct BlockContext(Vec); struct Builder<'a, 'tcx> { tcx: TyCtxt<'tcx>, + // FIXME(@lcnr): Why does this use an `infcx`, there should be + // no shared type inference going on here. I feel like it would + // clearer to manually construct one where necessary or to provide + // a nice API for non-type inference trait system checks. infcx: InferCtxt<'tcx>, region_scope_tree: &'tcx region::ScopeTree, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index da6b52ce0b8..4a64a1f0f3e 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -11,7 +11,7 @@ use rustc_middle::span_bug; use rustc_middle::thir::visit::Visitor; use rustc_middle::thir::*; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint::Level; use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_span::def_id::{DefId, LocalDefId}; @@ -37,7 +37,7 @@ struct UnsafetyVisitor<'a, 'tcx> { /// of the LHS and the span of the assignment expression. assignment_info: Option>, in_union_destructure: bool, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, inside_adt: bool, warnings: &'a mut Vec, @@ -213,7 +213,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { body_target_features: self.body_target_features, assignment_info: self.assignment_info, in_union_destructure: false, - param_env: self.param_env, + typing_env: self.typing_env, inside_adt: false, warnings: self.warnings, suggest_unsafe_block: self.suggest_unsafe_block, @@ -370,7 +370,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }; match rm { Mutability::Not => { - if !ty.is_freeze(self.tcx, self.param_env) { + if !ty.is_freeze(self.tcx, self.typing_env) { self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); } } @@ -566,9 +566,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { && adt_def.is_union() { if let Some(assigned_ty) = self.assignment_info { - if assigned_ty - .needs_drop(self.tcx, ty::TypingEnv::from_param_env(self.param_env)) - { + if assigned_ty.needs_drop(self.tcx, self.typing_env) { // This would be unsafe, but should be outright impossible since we // reject such unions. assert!( @@ -608,7 +606,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { if visitor.found { match borrow_kind { BorrowKind::Fake(_) | BorrowKind::Shared - if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) => + if !self.thir[arg].ty.is_freeze(self.tcx, self.typing_env) => { self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField) } @@ -1026,7 +1024,8 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { body_target_features, assignment_info: None, in_union_destructure: false, - param_env: tcx.param_env(def), + // FIXME(#132279): we're clearly in a body here. + typing_env: ty::TypingEnv::non_body_analysis(tcx, def), inside_adt: false, warnings: &mut warnings, suggest_unsafe_block: true, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 73fcbeaef82..033501c66db 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -7,6 +7,7 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_e use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, BindingMode, ByRef, HirId}; +use rustc_infer::traits::Reveal; use rustc_middle::bug; use rustc_middle::middle::limits::get_limit_size; use rustc_middle::thir::visit::Visitor; @@ -191,6 +192,15 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { } impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + // FIXME(#132279): We're in a body, should handle opaques. + debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing); + ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env: self.param_env, + } + } + #[instrument(level = "trace", skip(self, f))] fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) { let old_let_source = self.let_source; @@ -760,7 +770,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: return; }; - let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); + let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); let sess = cx.tcx.sess; diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 6b462198db6..1b3243e097e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -203,8 +203,6 @@ impl<'tcx> ConstToPat<'tcx> { fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box> { let span = self.span; let tcx = self.tcx(); - let param_env = self.param_env; - let kind = match ty.kind() { ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { // Extremely important check for all ADTs! Make sure they opted-in to be used in @@ -276,7 +274,9 @@ impl<'tcx> ConstToPat<'tcx> { // convert the dereferenced constant to a pattern that is the sub-pattern of the // deref pattern. _ => { - if !pointee_ty.is_sized(tcx, param_env) && !pointee_ty.is_slice() { + if !pointee_ty.is_sized(tcx, self.infcx.typing_env(self.param_env)) + && !pointee_ty.is_slice() + { let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; let e = tcx.dcx().emit_err(err); // We errored. Signal that in the pattern, so that follow up errors can be silenced. diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index a9600f77c0b..1b7c89fd251 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -3,7 +3,7 @@ use rustc_index::IndexVec; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::Session; use tracing::{debug, trace}; @@ -25,9 +25,9 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { return; } + let typing_env = body.typing_env(tcx); let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &mut body.local_decls; - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); // This pass inserts new blocks. Each insertion changes the Location for all // statements/blocks after. Iterating or visiting the MIR in order would require updating @@ -41,7 +41,7 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { let source_info = statement.source_info; let mut finder = - PointerFinder { tcx, local_decls, param_env, pointers: Vec::new() }; + PointerFinder { tcx, local_decls, typing_env, pointers: Vec::new() }; finder.visit_statement(statement, location); for (local, ty) in finder.pointers { @@ -65,7 +65,7 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { struct PointerFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, local_decls: &'a mut LocalDecls<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, pointers: Vec<(Place<'tcx>, Ty<'tcx>)>, } @@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PointerFinder<'a, 'tcx> { let pointee_ty = pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer"); // Ideally we'd support this in the future, but for now we are limited to sized types. - if !pointee_ty.is_sized(self.tcx, self.param_env) { + if !pointee_ty.is_sized(self.tcx, self.typing_env) { debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty); return; } diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 7d6ae9843b1..9b3443d3209 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -28,8 +28,8 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); + let typing_env = body.typing_env(tcx); + let ssa = SsaLocals::new(tcx, body, typing_env); let fully_moved = fully_moved_locals(&ssa, body); debug!(?fully_moved); diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index db72ec522a2..67b215c7c9d 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -208,7 +208,7 @@ pub(super) fn deduced_param_attrs<'tcx>( // blow-up in compile times: #113372 && tcx .normalize_erasing_regions(typing_env, local_decl.ty) - .is_freeze(tcx, typing_env.param_env), + .is_freeze(tcx, typing_env), }, ), ); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 27fe0ad72e7..5150cb752bd 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -120,12 +120,13 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); + let typing_env = body.typing_env(tcx); + let ssa = SsaLocals::new(tcx, body, typing_env); // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let mut state = VnState::new(tcx, body, param_env, &ssa, dominators, &body.local_decls); + let mut state = + VnState::new(tcx, body, typing_env.param_env, &ssa, dominators, &body.local_decls); ssa.for_each_assignment_mut( body.basic_blocks.as_mut_preserves_cfg(), |local, value, location| { @@ -241,7 +242,6 @@ enum Value<'tcx> { struct VnState<'body, 'tcx> { tcx: TyCtxt<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, - param_env: ty::ParamEnv<'tcx>, local_decls: &'body LocalDecls<'tcx>, /// Value stored in each local. locals: IndexVec>, @@ -281,7 +281,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { VnState { tcx, ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), - param_env, local_decls, locals: IndexVec::from_elem(None, local_decls), rev_locals: IndexVec::with_capacity(num_values), @@ -296,7 +295,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } fn typing_env(&self) -> ty::TypingEnv<'tcx> { - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } + self.ecx.typing_env() } #[instrument(level = "trace", skip(self), ret)] @@ -347,7 +346,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Only register the value if its type is `Sized`, as we will emit copies of it. let is_sized = !self.feature_unsized_locals - || self.local_decls[local].ty.is_sized(self.tcx, self.param_env); + || self.local_decls[local].ty.is_sized(self.tcx, self.typing_env()); if is_sized { self.rev_locals[value].push(local); } @@ -642,7 +641,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let ty = place.ty(self.local_decls, self.tcx).ty; if let Some(Mutability::Not) = ty.ref_mutability() && let Some(pointee_ty) = ty.builtin_deref(true) - && pointee_ty.is_freeze(self.tcx, self.param_env) + && pointee_ty.is_freeze(self.tcx, self.typing_env()) { // An immutable borrow `_x` always points to the same value for the // lifetime of the borrow, so we can merge all instances of `*_x`. @@ -1061,7 +1060,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let ty::RawPtr(from_pointee_ty, from_mtbl) = cast_from.kind() && let ty::RawPtr(_, output_mtbl) = output_pointer_ty.kind() && from_mtbl == output_mtbl - && from_pointee_ty.is_sized(self.tcx, self.param_env) + && from_pointee_ty.is_sized(self.tcx, self.typing_env()) { fields[0] = *cast_value; *data_pointer_ty = *cast_from; @@ -1383,7 +1382,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) = self.get(value) && let ty::RawPtr(to_pointee, _) = to.kind() - && to_pointee.is_sized(self.tcx, self.param_env) + && to_pointee.is_sized(self.tcx, self.typing_env()) { from = *data_pointer_ty; value = fields[0]; diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index fcb51fbddd9..00f6c3845d4 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -199,10 +199,7 @@ impl<'tcx> Inliner<'tcx> { let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty; for arg in args { - if !arg - .node - .ty(&caller_body.local_decls, self.tcx) - .is_sized(self.tcx, self.typing_env.param_env) + if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.typing_env) { // We do not allow inlining functions with unsized params. Inlining these functions // could create unsized locals, which are unsound and being phased out. diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 3911b0a2db6..67afd19aa73 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -451,7 +451,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if rvalue.has_param() { return None; } - if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env.param_env) { + if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env) { // the interpreter doesn't support unsized locals (only unsized arguments), // but rustc does (in a kinda broken way), so we have to skip them here return None; diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index b11b503e8d4..af438ac2177 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -85,8 +85,8 @@ impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation { } fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); + let typing_env = body.typing_env(tcx); + let ssa = SsaLocals::new(tcx, body, typing_env); let mut replacer = compute_replacement(tcx, body, &ssa); debug!(?replacer.targets); diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 84df666e34a..5653aef0aae 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -13,7 +13,7 @@ use rustc_middle::bug; use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::{ParamEnv, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use tracing::{debug, instrument, trace}; pub(super) struct SsaLocals { @@ -42,7 +42,7 @@ impl SsaLocals { pub(super) fn new<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> SsaLocals { let assignment_order = Vec::with_capacity(body.local_decls.len()); @@ -80,7 +80,7 @@ impl SsaLocals { // have already been marked as non-SSA. debug!(?visitor.borrowed_locals); for local in visitor.borrowed_locals.iter() { - if !body.local_decls[local].ty.is_freeze(tcx, param_env) { + if !body.local_decls[local].ty.is_freeze(tcx, typing_env) { visitor.assignments[local] = Set1::Many; } } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index ae0e6f594ee..724238ecfc9 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -623,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if let Operand::Copy(place) = operand { let ty = place.ty(&self.body.local_decls, self.tcx).ty; - if !ty.is_copy_modulo_regions(self.tcx, self.typing_env.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}")); } } @@ -989,7 +989,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } // FIXME: check `Thin` instead of `Sized` - if !in_pointee.is_sized(self.tcx, self.typing_env.param_env) { + if !in_pointee.is_sized(self.tcx, self.typing_env) { self.fail(location, "input pointer must be thin"); } } else { @@ -1004,7 +1004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) { self.fail(location, "slice metadata must be usize"); } - } else if pointee_ty.is_sized(self.tcx, self.typing_env.param_env) { + } else if pointee_ty.is_sized(self.tcx, self.typing_env) { if metadata_ty != self.tcx.types.unit { self.fail(location, "metadata for pointer-to-thin must be unit"); } @@ -1294,7 +1294,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self .tcx .normalize_erasing_regions(self.typing_env, op_ty) - .is_sized(self.tcx, self.typing_env.param_env) + .is_sized(self.tcx, self.typing_env) { self.fail( location, @@ -1304,7 +1304,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self .tcx .normalize_erasing_regions(self.typing_env, *target_type) - .is_sized(self.tcx, self.typing_env.param_env) + .is_sized(self.tcx, self.typing_env) { self.fail( location, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 1b94c627f81..8ee9ac3df72 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1036,7 +1036,7 @@ fn find_vtable_types_for_unsizing<'tcx>( let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { let typing_env = ty::TypingEnv::fully_monomorphized(); let type_has_metadata = |ty: Ty<'tcx>| -> bool { - if ty.is_sized(tcx.tcx, typing_env.param_env) { + if ty.is_sized(tcx.tcx, typing_env) { return false; } let tail = tcx.struct_tail_for_codegen(ty, typing_env); diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 8f1c8a29663..43244eb5dcb 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -32,8 +32,10 @@ impl<'tcx> InferCtxt<'tcx> { fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { let ty = self.resolve_vars_if_possible(ty); + // FIXME(#132279): This should be removed as it causes us to incorrectly + // handle opaques in their defining scope. if !(param_env, ty).has_infer() { - return ty.is_copy_modulo_regions(self.tcx, param_env); + return ty.is_copy_modulo_regions(self.tcx, self.typing_env(param_env)); } let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None); diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index e2283383196..a5a9125c8b5 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -397,7 +397,7 @@ fn adjust_for_rust_scalar<'tcx>( Some(kind) } else if let Some(pointee) = drop_target_pointee { // The argument to `drop_in_place` is semantically equivalent to a mutable reference. - Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env.param_env) }) + Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env) }) } else { None }; diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs index c26b41d8960..2157ab3c402 100644 --- a/compiler/rustc_ty_utils/src/common_traits.rs +++ b/compiler/rustc_ty_utils/src/common_traits.rs @@ -3,34 +3,33 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_trait_selection::traits; -fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, LangItem::Copy) } -fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, LangItem::Sized) } -fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, LangItem::Freeze) } -fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, LangItem::Unpin) } fn is_item_raw<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, item: LangItem, ) -> bool { - let (param_env, ty) = query.into_parts(); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(query.typing_env); let trait_def_id = tcx.require_lang_item(item, None); - let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); - traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id) + traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, query.value, trait_def_id) } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 02ee3f32915..092e140a600 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -105,7 +105,7 @@ fn map_error<'tcx>( // This is sometimes not a compile error if there are trivially false where clauses. // See `tests/ui/layout/trivial-bounds-sized.rs` for an example. assert!(field.layout.is_unsized(), "invalid layout error {err:#?}"); - if !field.ty.is_sized(cx.tcx(), cx.typing_env.param_env) { + if !field.ty.is_sized(cx.tcx(), cx.typing_env) { cx.tcx().dcx().delayed_bug(format!( "encountered unexpected unsized field in layout of {ty:?}: {field:#?}" )); @@ -236,7 +236,7 @@ fn layout_of_uncached<'tcx>( } let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee); - if pointee.is_sized(tcx, cx.typing_env.param_env) { + if pointee.is_sized(tcx, cx.typing_env) { return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); } @@ -594,8 +594,8 @@ fn layout_of_uncached<'tcx>( let maybe_unsized = def.is_struct() && def.non_enum_variant().tail_opt().is_some_and(|last_field| { - let param_env = tcx.param_env(def.did()); - !tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, param_env) + let typing_env = ty::TypingEnv::post_analysis(tcx, def.did()); + !tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, typing_env) }); let layout = cx @@ -620,11 +620,7 @@ fn layout_of_uncached<'tcx>( // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around. if cfg!(debug_assertions) && maybe_unsized - && def - .non_enum_variant() - .tail() - .ty(tcx, args) - .is_sized(tcx, cx.typing_env.param_env) + && def.non_enum_variant().tail().ty(tcx, args).is_sized(tcx, cx.typing_env) { let mut variants = variants; let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap(); diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index d462dbd9416..03ab3a55486 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -186,7 +186,7 @@ where } } - _ if component.is_copy_modulo_regions(tcx, self.typing_env.param_env) => (), + _ if component.is_copy_modulo_regions(tcx, self.typing_env) => (), ty::Closure(_, args) => { for upvar in args.as_closure().upvar_tys() { diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 31e4e79c00a..685fd922d91 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -42,7 +42,7 @@ pub(crate) fn synthesize_auto_trait_impls<'tcx>( }) .collect(); // We are only interested in case the type *doesn't* implement the `Sized` trait. - if !ty.is_sized(tcx, param_env) + if !ty.is_sized(tcx, ty::TypingEnv::from_param_env(param_env)) && let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() && let Some(impl_item) = synthesize_auto_trait_impl( cx, diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs index 86c5f6b9f0b..46d67e615c7 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs @@ -39,7 +39,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { (Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut)) // The `U` in `pointer::cast` have to be `Sized` // as explained here: https://github.com/rust-lang/rust/issues/60602. - && to_pointee_ty.is_sized(cx.tcx, cx.param_env) + && to_pointee_ty.is_sized(cx.tcx, cx.typing_env()) { let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir_ty.kind { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index f864b7a5a8a..9049739dddb 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1028,7 +1028,7 @@ fn report<'tcx>( State::ExplicitDeref { mutability } => { if is_block_like(expr) && let ty::Ref(_, ty, _) = data.adjusted_ty.kind() - && ty.is_sized(cx.tcx, cx.param_env) + && ty.is_sized(cx.tcx, cx.typing_env()) { // Rustc bug: auto deref doesn't work on block expression when targeting sized types. return; diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index c74ba088b78..175d92d2d79 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -198,7 +198,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) // primitive types are never mutable ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, ty::Adt(adt, args) => { - tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env) + tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.typing_env()) || matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc)) && args.types().any(|ty| is_mutable_ty(cx, ty, tys)) }, diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 0e488cee6b7..5db28e9ae9b 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { let has_interior_mutability = !cx .typeck_results() .node_type(canonical_id) - .is_freeze(cx.tcx, cx.param_env); + .is_freeze(cx.tcx, cx.typing_env()); if has_interior_mutability { return; } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs index 223b0630bfd..7aa13d8d5b6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs @@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: _ => {}, } } - requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); + requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); break; } }, @@ -158,9 +158,9 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: } if can_lint - && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)) + && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())) // This case could be handled, but a fair bit of care would need to be taken. - && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.param_env)) + && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env())) { if requires_deref { edits.push((param.span.shrink_to_lo(), "&".into())); diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index 6cddd7ea813..e2ab5e98504 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -80,7 +80,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> { "generally you want to avoid `&mut &mut _` if possible", ); } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() { - if ty.peel_refs().is_sized(self.cx.tcx, self.cx.param_env) { + if ty.peel_refs().is_sized(self.cx.tcx, self.cx.typing_env()) { span_lint_hir( self.cx, MUT_MUT, diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 0775d7abdbb..ad0ab148530 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -180,7 +180,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if !is_self(arg) && !ty.is_mutable_ptr() && !is_copy(cx, ty) - && ty.is_sized(cx.tcx, cx.param_env) + && ty.is_sized(cx.tcx, cx.typing_env()) && !allowed_traits.iter().any(|&t| { implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, t, None, [Option::< ty::GenericArg<'tcx>, diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index a00fd01a62e..f69cb9be4ca 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex { let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) + let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); let sugg = if let Some(else_inner) = r#else { if eq_expr_value(cx, caller, peel_blocks(else_inner)) { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 0772b284968..bf6700b1b6b 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>( |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { if from_mutbl == to_mutbl - && to_pointee_ty.is_sized(cx.tcx, cx.param_env) + && to_pointee_ty.is_sized(cx.tcx, cx.typing_env()) && msrv.meets(msrvs::POINTER_CAST) { diag.span_suggestion_verbose( diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 4dc1290e8b1..48d65eb15d9 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -206,12 +206,12 @@ fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: T continue; }, (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _)), _) - if !unsized_ty.is_sized(cx.tcx, cx.param_env) => + if !unsized_ty.is_sized(cx.tcx, cx.typing_env()) => { (true, false) }, (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _))) - if !unsized_ty.is_sized(cx.tcx, cx.param_env) => + if !unsized_ty.is_sized(cx.tcx, cx.typing_env()) => { (false, true) }, diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index 1a656088b17..de3456a8ba5 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: // here because `mod.rs` guarantees this lint is only run on types outside of bodies and // is not run on locals. let ty = lower_ty(cx.tcx, hir_ty); - if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.param_env) { + if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.typing_env()) { return false; } hir_ty.span diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index 230239335c6..9b236d3bda5 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -37,7 +37,7 @@ pub(super) fn check<'tcx>( && let boxed_alloc_ty = last.args.get(1) && let ty_ty = lower_ty(cx.tcx, boxed_ty) && !ty_ty.has_escaping_bound_vars() - && ty_ty.is_sized(cx.tcx, cx.param_env) + && ty_ty.is_sized(cx.tcx, cx.typing_env()) && let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()) && ty_ty_size < box_size_threshold // https://github.com/rust-lang/rust-clippy/issues/7114 diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs index 14f4aa6676b..34df1d5560a 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs @@ -82,7 +82,7 @@ impl UnnecessaryBoxReturns { // It's sometimes useful to return Box if T is unsized, so don't lint those. // Also, don't lint if we know that T is very large, in which case returning // a Box may be beneficial. - if boxed_ty.is_sized(cx.tcx, cx.param_env) && approx_ty_size(cx, boxed_ty) <= self.maximum_size { + if boxed_ty.is_sized(cx.tcx, cx.typing_env()) && approx_ty_size(cx, boxed_ty) <= self.maximum_size { span_lint_and_then( cx, UNNECESSARY_BOX_RETURNS, diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 2aad867dc0d..fff516b730d 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain; /// Checks if the given type implements copy. pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(cx.tcx, cx.param_env) + ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) } /// This checks whether a given type is known to implement Debug. diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 745316913d9..f46557ac630 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -12,7 +12,6 @@ use std::{cmp, mem}; use rustc_abi::{BackendRepr, Size}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Mutability, RetagKind}; -use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use self::diagnostics::{RetagCause, RetagInfo}; @@ -71,7 +70,7 @@ impl NewPermission { access: None, protector: None, } - } else if pointee.is_unpin(*cx.tcx, cx.param_env()) { + } else if pointee.is_unpin(*cx.tcx, cx.typing_env()) { // A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`. NewPermission::Uniform { perm: Permission::Unique, @@ -129,7 +128,7 @@ impl NewPermission { fn from_box_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self { // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling). let pointee = ty.builtin_deref(true).unwrap(); - if pointee.is_unpin(*cx.tcx, cx.param_env()) { + if pointee.is_unpin(*cx.tcx, cx.typing_env()) { // A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only // a weak protector). NewPermission::Uniform { @@ -608,7 +607,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { match new_perm { NewPermission::Uniform { perm, .. } => write!(kind_str, "{perm:?} permission").unwrap(), - NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.param_env()) => + NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.typing_env()) => write!(kind_str, "{freeze_perm:?} permission").unwrap(), NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } => write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(), diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 255a3578aae..8f8e29846c9 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,6 +1,5 @@ use rustc_abi::{BackendRepr, Size}; use rustc_middle::mir::{Mutability, RetagKind}; -use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use rustc_span::def_id::DefId; @@ -132,8 +131,8 @@ impl<'tcx> NewPermission { kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>, ) -> Option { - let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.param_env()); - let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.param_env()); + let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env()); + let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env()); let is_protected = kind == RetagKind::FnEntry; // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`, // interior mutability and protectors interact poorly. @@ -164,10 +163,10 @@ impl<'tcx> NewPermission { zero_size: bool, ) -> Option { let pointee = ty.builtin_deref(true).unwrap(); - pointee.is_unpin(*cx.tcx, cx.param_env()).then_some(()).map(|()| { + pointee.is_unpin(*cx.tcx, cx.typing_env()).then_some(()).map(|()| { // Regular `Unpin` box, give it `noalias` but only a weak protector // because it is valid to deallocate it within the function. - let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.param_env()); + let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.typing_env()); let protected = kind == RetagKind::FnEntry; let initial_state = Permission::new_reserved(ty_is_freeze, protected); Self { @@ -521,7 +520,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Note: if we were to inline `new_reserved` below we would find out that // `ty_is_freeze` is eventually unused because it appears in a `ty_is_freeze || true`. // We are nevertheless including it here for clarity. - let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.param_env()); + let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env()); // Retag it. With protection! That is the entire point. let new_perm = NewPermission { initial_state: Permission::new_reserved(ty_is_freeze, /* protected */ true), -- cgit 1.4.1-3-g733a5 From 7a90e84f4d760cb49035f1446d4c6cfb3993aad2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 19 Nov 2024 20:10:42 +0100 Subject: `InterpCx` store `TypingEnv` instead of a `ParamEnv` --- .../rustc_codegen_cranelift/src/intrinsics/mod.rs | 6 ++- compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 5 +- .../src/const_eval/eval_queries.rs | 50 ++++++++----------- .../rustc_const_eval/src/const_eval/machine.rs | 2 +- compiler/rustc_const_eval/src/const_eval/mod.rs | 8 +-- .../rustc_const_eval/src/const_eval/valtrees.rs | 25 +++++----- compiler/rustc_const_eval/src/interpret/call.rs | 58 +++++++++++----------- compiler/rustc_const_eval/src/interpret/cast.rs | 4 +- .../rustc_const_eval/src/interpret/eval_context.rs | 43 ++++++++-------- compiler/rustc_const_eval/src/interpret/intern.rs | 2 +- .../rustc_const_eval/src/interpret/intrinsics.rs | 9 ++-- compiler/rustc_const_eval/src/interpret/memory.rs | 4 +- .../rustc_const_eval/src/interpret/operator.rs | 2 +- compiler/rustc_const_eval/src/interpret/place.rs | 4 +- compiler/rustc_const_eval/src/interpret/stack.rs | 4 +- compiler/rustc_const_eval/src/interpret/step.rs | 3 +- .../rustc_const_eval/src/interpret/validity.rs | 13 +++-- compiler/rustc_const_eval/src/lib.rs | 7 ++- .../rustc_const_eval/src/util/caller_location.rs | 2 +- .../src/util/check_validity_requirement.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 4 +- compiler/rustc_middle/src/mir/interpret/queries.rs | 32 ++++++------ compiler/rustc_middle/src/query/keys.rs | 12 ----- compiler/rustc_middle/src/query/mod.rs | 6 +-- compiler/rustc_middle/src/ty/instance.rs | 4 +- compiler/rustc_middle/src/ty/mod.rs | 3 +- .../rustc_mir_transform/src/dataflow_const_prop.rs | 2 +- compiler/rustc_mir_transform/src/gvn.rs | 9 ++-- compiler/rustc_mir_transform/src/jump_threading.rs | 2 +- .../rustc_mir_transform/src/known_panics_lint.rs | 2 +- compiler/rustc_smir/src/rustc_smir/context.rs | 4 +- .../clippy/clippy_lints/src/non_copy_const.rs | 6 +-- .../miri/src/borrow_tracker/stacked_borrows/mod.rs | 6 +-- .../miri/src/borrow_tracker/tree_borrows/mod.rs | 10 ++-- src/tools/miri/src/eval.rs | 2 +- src/tools/miri/src/machine.rs | 2 +- 36 files changed, 167 insertions(+), 192 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index c663f6fc2d3..3318c0797ec 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -744,7 +744,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let const_val = fx .tcx - .const_eval_instance(ty::ParamEnv::reveal_all(), instance, source_info.span) + .const_eval_instance( + ty::TypingEnv::fully_monomorphized(), + instance, + source_info.span, + ) .unwrap(); let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty); ret.write_cvalue(fx, val); diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index c35d0b90706..299b98c0a4f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -146,10 +146,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | sym::type_id | sym::type_name | sym::variant_count => { - let value = bx - .tcx() - .const_eval_instance(ty::ParamEnv::reveal_all(), instance, span) - .unwrap(); + let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap(); OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx) } sym::arith_offset => { diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index ca3ee6773a0..64331eea75c 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -7,7 +7,6 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo}; use rustc_middle::mir::{self, ConstAlloc, ConstValue}; use rustc_middle::query::TyCtxtAt; -use rustc_middle::traits::Reveal; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -31,7 +30,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( cid: GlobalId<'tcx>, body: &'tcx mir::Body<'tcx>, ) -> InterpResult<'tcx, R> { - trace!(?ecx.param_env); + trace!(?ecx.typing_env); let tcx = *ecx.tcx; assert!( cid.promoted.is_some() @@ -126,14 +125,14 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>( tcx: TyCtxt<'tcx>, root_span: Span, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, can_access_mut_global: CanAccessMutGlobal, ) -> CompileTimeInterpCx<'tcx> { - debug!("mk_eval_cx: {:?}", param_env); + debug!("mk_eval_cx: {:?}", typing_env); InterpCx::new( tcx, root_span, - param_env, + typing_env, CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No), ) } @@ -142,11 +141,11 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>( /// Returns both the context and an `OpTy` that represents the constant. pub fn mk_eval_cx_for_const_val<'tcx>( tcx: TyCtxtAt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, val: mir::ConstValue<'tcx>, ty: Ty<'tcx>, ) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> { - let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No); + let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No); // FIXME: is it a problem to discard the error here? let op = ecx.const_val_to_op(val, ty, None).discard_err()?; Some((ecx, op)) @@ -221,7 +220,7 @@ pub(super) fn op_to_const<'tcx>( let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs debug_assert!( matches!( - ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(), + ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env).kind(), ty::Str | ty::Slice(..), ), "`ConstValue::Slice` is for slice-tailed types only, but got {}", @@ -245,7 +244,7 @@ pub(super) fn op_to_const<'tcx>( pub(crate) fn turn_into_const_value<'tcx>( tcx: TyCtxt<'tcx>, constant: ConstAlloc<'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, ) -> ConstValue<'tcx> { let cid = key.value; let def_id = cid.instance.def.def_id(); @@ -254,7 +253,7 @@ pub(crate) fn turn_into_const_value<'tcx>( let ecx = mk_eval_cx_to_read_const_val( tcx, tcx.def_span(key.value.instance.def_id()), - key.param_env, + key.typing_env, CanAccessMutGlobal::from(is_static), ); @@ -274,23 +273,16 @@ pub(crate) fn turn_into_const_value<'tcx>( #[instrument(skip(tcx), level = "debug")] pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { - // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of - // opaque types. This is needed for trivial things like `size_of`, but also for using associated - // types that are not specified in the opaque type. - assert_eq!(key.param_env.reveal(), Reveal::All); - let typing_env = - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: key.param_env }; - // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // Catch such calls and evaluate them instead of trying to load a constant's MIR. if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def { - let ty = key.value.instance.ty(tcx, typing_env); + let ty = key.value.instance.ty(tcx, key.typing_env); let ty::FnDef(_, args) = ty.kind() else { bug!("intrinsic with type {:?}", ty); }; - return eval_nullary_intrinsic(tcx, key.param_env, def_id, args).report_err().map_err( + return eval_nullary_intrinsic(tcx, key.typing_env, def_id, args).report_err().map_err( |error| { let span = tcx.def_span(def_id); @@ -317,7 +309,7 @@ pub fn eval_static_initializer_provider<'tcx>( let instance = ty::Instance::mono(tcx, def_id.to_def_id()); let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None }; - eval_in_interpreter(tcx, cid, ty::ParamEnv::reveal_all()) + eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized()) } pub trait InterpretationResult<'tcx> { @@ -342,16 +334,14 @@ impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> { #[instrument(skip(tcx), level = "debug")] pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { // This shouldn't be used for statics, since statics are conceptually places, // not values -- so what we do here could break pointer identity. assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id())); - // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of - // opaque types. This is needed for trivial things like `size_of`, but also for using associated - // types that are not specified in the opaque type. - - assert_eq!(key.param_env.reveal(), Reveal::All); + // Const eval always happens in PostAnalysis mode . See the comment in + // `InterpCx::new` for more details. + debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis); if cfg!(debug_assertions) { // Make sure we format the instance even if we do not print it. // This serves as a regression test against an ICE on printing. @@ -362,13 +352,13 @@ pub fn eval_to_allocation_raw_provider<'tcx>( trace!("const eval: {:?} ({})", key, instance); } - eval_in_interpreter(tcx, key.value, key.param_env) + eval_in_interpreter(tcx, key.value, key.typing_env) } fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( tcx: TyCtxt<'tcx>, cid: GlobalId<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Result { let def = cid.instance.def.def_id(); let is_static = tcx.is_static(def); @@ -376,7 +366,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( let mut ecx = InterpCx::new( tcx, tcx.def_span(def), - param_env, + typing_env, // Statics (and promoteds inside statics) may access mutable global memory, because unlike consts // they do not have to behave "as if" they were evaluated at runtime. // For consts however we want to ensure they behave "as if" they were evaluated at runtime, diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 347b1557d87..db82050c73c 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -667,7 +667,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { .is_some_and(|p| !p.immutable()) { // That next check is expensive, that's why we have all the guards above. - let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env()); + let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env); let place = ecx.ref_to_mplace(val)?; let new_place = if is_immutable { place.map_provenance(CtfeProvenance::as_immutable) diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index d5012236c34..8cbdcd68e13 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -38,8 +38,8 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>( val: mir::ConstValue<'tcx>, ty: Ty<'tcx>, ) -> Option> { - let param_env = ty::ParamEnv::reveal_all(); - let (ecx, op) = mk_eval_cx_for_const_val(tcx, param_env, val, ty)?; + let typing_env = ty::TypingEnv::fully_monomorphized(); + let (ecx, op) = mk_eval_cx_for_const_val(tcx, typing_env, val, ty)?; // We go to `usize` as we cannot allocate anything bigger anyway. let (field_count, variant, down) = match ty.kind() { @@ -76,10 +76,12 @@ pub fn tag_for_variant_provider<'tcx>( ) -> Option { assert!(ty.is_enum()); + // FIXME: This uses an empty `TypingEnv` even though + // it may be used by a generic CTFE. let ecx = InterpCx::new( tcx, ty.default_span(tcx), - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), crate::const_eval::DummyMachine, ); diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 64bedea3b3f..515028e6826 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -2,7 +2,6 @@ use rustc_abi::{BackendRepr, VariantIdx}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; -use rustc_middle::ty::solve::Reveal; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::DUMMY_SP; @@ -229,16 +228,19 @@ fn create_valtree_place<'tcx>( /// Evaluates a constant and turns it into a type-level constant value. pub(crate) fn eval_to_valtree<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, cid: GlobalId<'tcx>, ) -> EvalToValTreeResult<'tcx> { - let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?; + // Const eval always happens in PostAnalysis mode . See the comment in + // `InterpCx::new` for more details. + debug_assert_eq!(typing_env.typing_mode, ty::TypingMode::PostAnalysis); + let const_alloc = tcx.eval_to_allocation_raw(typing_env.as_query_input(cid))?; // FIXME Need to provide a span to `eval_to_valtree` let ecx = mk_eval_cx_to_read_const_val( tcx, DUMMY_SP, - param_env, + typing_env, // It is absolutely crucial for soundness that // we do not read from mutable memory. CanAccessMutGlobal::No, @@ -273,7 +275,8 @@ pub(crate) fn eval_to_valtree<'tcx>( #[instrument(skip(tcx), level = "debug", ret)] pub fn valtree_to_const_value<'tcx>( tcx: TyCtxt<'tcx>, - param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, valtree: ty::ValTree<'tcx>, ) -> mir::ConstValue<'tcx> { // Basic idea: We directly construct `Scalar` values from trivial `ValTree`s @@ -282,10 +285,6 @@ pub fn valtree_to_const_value<'tcx>( // the `ValTree` and using `place_projection` and `place_field` to // create inner `MPlace`s which are filled recursively. // FIXME Does this need an example? - let (param_env, ty) = param_env_ty.into_parts(); - debug_assert_eq!(param_env.reveal(), Reveal::All); - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; - match *ty.kind() { ty::FnDef(..) => { assert!(valtree.unwrap_branch().is_empty()); @@ -299,10 +298,10 @@ pub fn valtree_to_const_value<'tcx>( ), } } - ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree), + ty::Pat(ty, _) => valtree_to_const_value(tcx, typing_env, ty, valtree), ty::Ref(_, inner_ty, _) => { let mut ecx = - mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No); + mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No); let imm = valtree_to_ref(&mut ecx, valtree, inner_ty); let imm = ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap()); @@ -324,14 +323,14 @@ pub fn valtree_to_const_value<'tcx>( for (i, &inner_valtree) in branches.iter().enumerate() { let field = layout.field(&LayoutCx::new(tcx, typing_env), i); if !field.is_zst() { - return valtree_to_const_value(tcx, param_env.and(field.ty), inner_valtree); + return valtree_to_const_value(tcx, typing_env, field.ty, inner_valtree); } } bug!("could not find non-ZST field during in {layout:#?}"); } let mut ecx = - mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No); + mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No); // Need to create a place for this valtree. let place = create_valtree_place(&mut ecx, layout, valtree); diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 6cfe4b21907..ed4a1a9e647 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -215,7 +215,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Even if `ty` is normalized, the search for the unsized tail will project // to fields, which can yield non-normalized types. So we need to provide a // normalization function. - let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env(), ty); + let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env, ty); ty.ptr_metadata_ty(*self.tcx, normalize) }; return interp_ok(meta_ty(caller) == meta_ty(callee)); @@ -652,35 +652,35 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // Obtain the underlying trait we are working on, and the adjusted receiver argument. - let (trait_, dyn_ty, adjusted_recv) = - if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() { - let recv = self.unpack_dyn_star(&receiver_place, data)?; + let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) = + receiver_place.layout.ty.kind() + { + let recv = self.unpack_dyn_star(&receiver_place, data)?; - (data.principal(), recv.layout.ty, recv.ptr()) - } else { - // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. - // (For that reason we also cannot use `unpack_dyn_trait`.) - let receiver_tail = self - .tcx - .struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env()); - let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { - span_bug!( - self.cur_span(), - "dynamic call on non-`dyn` type {}", - receiver_tail - ) - }; - assert!(receiver_place.layout.is_unsized()); - - // Get the required information from the vtable. - let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; - let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; - - // It might be surprising that we use a pointer as the receiver even if this - // is a by-val case; this works because by-val passing of an unsized `dyn - // Trait` to a function is actually desugared to a pointer. - (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) + (data.principal(), recv.layout.ty, recv.ptr()) + } else { + // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. + // (For that reason we also cannot use `unpack_dyn_trait`.) + let receiver_tail = + self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env); + let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { + span_bug!( + self.cur_span(), + "dynamic call on non-`dyn` type {}", + receiver_tail + ) }; + assert!(receiver_place.layout.is_unsized()); + + // Get the required information from the vtable. + let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; + let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; + + // It might be surprising that we use a pointer as the receiver even if this + // is a by-val case; this works because by-val passing of an unsized `dyn + // Trait` to a function is actually desugared to a pointer. + (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) + }; // Now determine the actual method to call. Usually we use the easy way of just // looking up the method at index `idx`. @@ -704,7 +704,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let concrete_method = Instance::expect_resolve_for_vtable( tcx, - self.typing_env(), + self.typing_env, def_id, instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 2d1bb5c9551..c95e51f0a1f 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -83,7 +83,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::FnDef(def_id, args) => { let instance = ty::Instance::resolve_for_fn_ptr( *self.tcx, - self.typing_env(), + self.typing_env, def_id, args, ) @@ -384,7 +384,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { // A -> A conversion let (src_pointee_ty, dest_pointee_ty) = - self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env()); + self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env); match (src_pointee_ty.kind(), dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 31ce1600ce7..42fdf32e91e 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1,10 +1,12 @@ +use std::assert_matches::debug_assert_matches; + use either::{Left, Right}; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::at::ToTrace; -use rustc_infer::traits::{ObligationCause, Reveal}; +use rustc_infer::traits::ObligationCause; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ @@ -36,8 +38,9 @@ pub struct InterpCx<'tcx, M: Machine<'tcx>> { /// we are evaluating (if this is CTFE). pub tcx: TyCtxtAt<'tcx>, - /// Bounds in scope for polymorphic evaluations. - pub(crate) param_env: ty::ParamEnv<'tcx>, + /// The current context in case we're evaluating in a + /// polymorphic context. This always uses `ty::TypingMode::PostAnalysis` + pub typing_env: ty::TypingEnv<'tcx>, /// The virtual memory system. pub memory: Memory<'tcx, M>, @@ -68,7 +71,7 @@ where M: Machine<'tcx>, { fn typing_env(&self) -> ty::TypingEnv<'tcx> { - self.typing_env() + self.typing_env } } @@ -189,25 +192,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn new( tcx: TyCtxt<'tcx>, root_span: Span, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, machine: M, ) -> Self { + // Const eval always happens in post analysis mode in order to be able to use the hidden types of + // opaque types. This is needed for trivial things like `size_of`, but also for using associated + // types that are not specified in the opaque type. We also use MIR bodies whose opaque types have + // already been revealed, so we'd be able to at least partially observe the hidden types anyways. + debug_assert_matches!(typing_env.typing_mode, ty::TypingMode::PostAnalysis); InterpCx { machine, tcx: tcx.at(root_span), - param_env, + typing_env, memory: Memory::new(), recursion_limit: tcx.recursion_limit(), } } - /// During CTFE we're always in `PostAnalysis` mode. - #[inline(always)] - pub fn typing_env(&self) -> ty::TypingEnv<'tcx> { - debug_assert_eq!(self.param_env.reveal(), Reveal::All); - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } - } - /// Returns the span of the currently executed statement/terminator. /// This is the span typically used for error reporting. #[inline(always)] @@ -250,7 +251,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { #[inline] pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(*self.tcx, self.typing_env()) + ty.is_freeze(*self.tcx, self.typing_env) } pub fn load_mir( @@ -296,7 +297,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .instance .try_instantiate_mir_and_normalize_erasing_regions( *self.tcx, - self.typing_env(), + self.typing_env, ty::EarlyBinder::bind(value), ) .map_err(|_| ErrorHandled::TooGeneric(self.cur_span())) @@ -309,9 +310,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { args: GenericArgsRef<'tcx>, ) -> InterpResult<'tcx, ty::Instance<'tcx>> { trace!("resolve: {:?}, {:#?}", def, args); - trace!("param_env: {:#?}", self.param_env); + trace!("typing_env: {:#?}", self.typing_env); trace!("args: {:#?}", args); - match ty::Instance::try_resolve(*self.tcx, self.typing_env(), def, args) { + match ty::Instance::try_resolve(*self.tcx, self.typing_env, def, args) { Ok(Some(instance)) => interp_ok(instance), Ok(None) => throw_inval!(TooGeneric), @@ -332,7 +333,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return true; } // Slow path: spin up an inference context to check if these traits are sufficiently equal. - let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env()); + let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy_with_span(self.cur_span()); // equate the two trait refs after normalization @@ -564,10 +565,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let val = if self.tcx.is_static(gid.instance.def_id()) { let alloc_id = self.tcx.reserve_and_set_static_alloc(gid.instance.def_id()); - let ty = instance.ty(self.tcx.tcx, self.typing_env()); + let ty = instance.ty(self.tcx.tcx, self.typing_env); mir::ConstAlloc { alloc_id, ty } } else { - self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.param_env.and(gid)))? + self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.typing_env.as_query_input(gid)))? }; self.raw_const_to_mplace(val) } @@ -579,7 +580,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| { - let const_val = val.eval(*ecx.tcx, ecx.typing_env(), span).map_err(|err| { + let const_val = val.eval(*ecx.tcx, ecx.typing_env, span).map_err(|err| { if M::ALL_CONSTS_ARE_PRECHECKED { match err { ErrorHandled::TooGeneric(..) => {}, diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 2d695688ae5..0cbb3b157f3 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -165,7 +165,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval InternKind::Static(Mutability::Not) => { ( // Outermost allocation is mutable if `!Freeze`. - if ret.layout.ty.is_freeze(*ecx.tcx, ecx.typing_env()) { + if ret.layout.ty.is_freeze(*ecx.tcx, ecx.typing_env) { Mutability::Not } else { Mutability::Mut diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index c8859ab3e88..a79923e8555 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -34,13 +34,12 @@ pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAll /// inside an `InterpCx` and instead have their value computed directly from rustc internal info. pub(crate) fn eval_nullary_intrinsic<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, ) -> InterpResult<'tcx, ConstValue<'tcx>> { let tp_ty = args.type_at(0); let name = tcx.item_name(def_id); - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; interp_ok(match name { sym::type_name => { ensure_monomorphic_enough(tcx, tp_ty)?; @@ -152,8 +151,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { sym::type_name => Ty::new_static_str(self.tcx.tcx), _ => bug!(), }; - let val = - self.ctfe_query(|tcx| tcx.const_eval_global_id(self.param_env, gid, tcx.span))?; + let val = self + .ctfe_query(|tcx| tcx.const_eval_global_id(self.typing_env, gid, tcx.span))?; let val = self.const_val_to_op(val, ty, Some(dest.layout))?; self.copy_op(&val, dest)?; } @@ -358,7 +357,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let should_panic = !self .tcx - .check_validity_requirement((requirement, self.typing_env().as_query_input(ty))) + .check_validity_requirement((requirement, self.typing_env.as_query_input(ty))) .map_err(|_| err_inval!(TooGeneric))?; if should_panic { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 9bae9c4b310..277d293597a 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -859,8 +859,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // # Global allocations if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) { - let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env()); - let mutbl = global_alloc.mutability(*self.tcx, self.typing_env()); + let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env); + let mutbl = global_alloc.mutability(*self.tcx, self.typing_env); let kind = match global_alloc { GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData, GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"), diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 201f1b5dc62..1fa5dcbd24f 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -533,7 +533,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } OffsetOf(fields) => { let val = - self.tcx.offset_of_subfield(self.typing_env(), layout, fields.iter()).bytes(); + self.tcx.offset_of_subfield(self.typing_env, layout, fields.iter()).bytes(); ImmTy::from_uint(val, usize_layout()) } UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 13fcccca76b..2beec544fad 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -540,7 +540,7 @@ where )?; if !mir_assign_valid_types( *self.tcx, - self.typing_env(), + self.typing_env, self.layout_of(normalized_place_ty)?, place.layout, ) { @@ -871,7 +871,7 @@ where // We do NOT compare the types for equality, because well-typed code can // actually "transmute" `&mut T` to `&T` in an assignment without a cast. let layout_compat = - mir_assign_valid_types(*self.tcx, self.typing_env(), src.layout(), dest.layout()); + mir_assign_valid_types(*self.tcx, self.typing_env, src.layout(), dest.layout()); if !allow_transmute && !layout_compat { span_bug!( self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 037c1a233ee..8ce11c71b8b 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -379,7 +379,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { for &const_ in body.required_consts() { let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?; - c.eval(*self.tcx, self.typing_env(), const_.span).map_err(|err| { + c.eval(*self.tcx, self.typing_env, const_.span).map_err(|err| { err.emit_note(*self.tcx); err })?; @@ -596,7 +596,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return interp_ok(layout); } - let layout = from_known_layout(self.tcx, self.typing_env(), layout, || { + let layout = from_known_layout(self.tcx, self.typing_env, layout, || { let local_ty = frame.body.local_decls[local].ty; let local_ty = self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index d4525243642..98aca37e73e 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -418,8 +418,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .collect::>>()?; let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx); - let fn_sig = - self.tcx.normalize_erasing_late_bound_regions(self.typing_env(), fn_sig_binder); + let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, fn_sig_binder); let extra_args = &args[fn_sig.inputs().len()..]; let extra_args = self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty)); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 9ff24a01689..273eaf42d87 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -448,7 +448,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { meta: MemPlaceMeta, pointee: TyAndLayout<'tcx>, ) -> InterpResult<'tcx> { - let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env()); + let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env); match tail.kind() { ty::Dynamic(data, _, ty::Dyn) => { let vtable = meta.unwrap_meta().to_pointer(self.ecx)?; @@ -568,7 +568,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); }; let (size, _align) = - global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env()); + global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env); if let GlobalAlloc::Static(did) = global_alloc { let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { @@ -619,7 +619,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { }; // Determine what it actually points to. let alloc_actual_mutbl = - global_alloc.mutability(*self.ecx.tcx, self.ecx.typing_env()); + global_alloc.mutability(*self.ecx.tcx, self.ecx.typing_env); // Mutable pointer to immutable memory is no good. if ptr_expected_mutbl == Mutability::Mut && alloc_actual_mutbl == Mutability::Not @@ -848,7 +848,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) { let tcx = *self.ecx.tcx; // Everything must be already interned. - let mutbl = tcx.global_alloc(alloc_id).mutability(tcx, self.ecx.typing_env()); + let mutbl = tcx.global_alloc(alloc_id).mutability(tcx, self.ecx.typing_env); if let Some((_, alloc)) = self.ecx.memory.alloc_map.get(alloc_id) { assert_eq!(alloc.mutability, mutbl); } @@ -955,7 +955,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ) -> Cow<'e, RangeSet> { assert!(layout.ty.is_union()); assert!(layout.is_sized(), "there are no unsized unions"); - let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env()); + let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env); return M::cached_union_data_range(ecx, layout.ty, || { let mut out = RangeSet(Vec::new()); union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out); @@ -1085,8 +1085,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, ) -> InterpResult<'tcx> { // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory. if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) { - if !val.layout.is_zst() - && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env()) + if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env) { if !self.in_mutable_memory(val) { throw_validation_failure!(self.path, UnsafeCellInImmutable); diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 527236b2c22..2a7408f1c70 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -40,14 +40,13 @@ pub fn provide(providers: &mut Providers) { providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider; providers.eval_static_initializer = const_eval::eval_static_initializer_provider; providers.hooks.const_caller_location = util::caller_location::const_caller_location_provider; - providers.eval_to_valtree = |tcx, param_env_and_value| { - let (param_env, raw) = param_env_and_value.into_parts(); - const_eval::eval_to_valtree(tcx, param_env, raw) + providers.eval_to_valtree = |tcx, ty::PseudoCanonicalInput { typing_env, value }| { + const_eval::eval_to_valtree(tcx, typing_env, value) }; providers.hooks.try_destructure_mir_constant_for_user_output = const_eval::try_destructure_mir_constant_for_user_output; providers.valtree_to_const_val = |tcx, (ty, valtree)| { - const_eval::valtree_to_const_value(tcx, ty::ParamEnv::reveal_all().and(ty), valtree) + const_eval::valtree_to_const_value(tcx, ty::TypingEnv::fully_monomorphized(), ty, valtree) }; providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| { util::check_validity_requirement(tcx, init_kind, param_env_and_ty) diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs index 7f4c36835e4..9bf16d4fe16 100644 --- a/compiler/rustc_const_eval/src/util/caller_location.rs +++ b/compiler/rustc_const_eval/src/util/caller_location.rs @@ -60,7 +60,7 @@ pub(crate) fn const_caller_location_provider( let mut ecx = mk_eval_cx_to_read_const_val( tcx.tcx, tcx.span, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), CanAccessMutGlobal::No, ); diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 1afc910ce8f..651a797e97c 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -49,7 +49,7 @@ fn check_validity_requirement_strict<'tcx>( ) -> Result> { let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); - let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env.param_env, machine); + let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env, machine); let allocated = cx .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap)) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 5830636c6e8..629cca88043 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -188,8 +188,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) { DefKind::Const if tcx.generics_of(item_def_id).is_empty() => { let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty()); let cid = GlobalId { instance, promoted: None }; - let param_env = ty::ParamEnv::reveal_all(); - tcx.ensure().eval_to_const_value_raw(param_env.and(cid)); + let typing_env = ty::TypingEnv::fully_monomorphized(); + tcx.ensure().eval_to_const_value_raw(typing_env.as_query_input(cid)); } _ => (), } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 7092f87a7d1..6eeafe18b35 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -25,8 +25,8 @@ impl<'tcx> TyCtxt<'tcx> { let args = GenericArgs::identity_for_item(self, def_id); let instance = ty::Instance::new(def_id, args); let cid = GlobalId { instance, promoted: None }; - let param_env = self.param_env(def_id).with_reveal_all_normalized(self); - self.const_eval_global_id(param_env, cid, DUMMY_SP) + let typing_env = ty::TypingEnv::post_analysis(self, def_id); + self.const_eval_global_id(typing_env, cid, DUMMY_SP) } /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts @@ -41,8 +41,8 @@ impl<'tcx> TyCtxt<'tcx> { let args = GenericArgs::identity_for_item(self, def_id); let instance = ty::Instance::new(def_id, args); let cid = GlobalId { instance, promoted: None }; - let param_env = self.param_env(def_id).with_reveal_all_normalized(self); - let inputs = self.erase_regions(param_env.and(cid)); + let typing_env = ty::TypingEnv::post_analysis(self, def_id); + let inputs = self.erase_regions(typing_env.as_query_input(cid)); self.eval_to_allocation_raw(inputs) } @@ -76,7 +76,7 @@ impl<'tcx> TyCtxt<'tcx> { match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; - self.const_eval_global_id(typing_env.param_env, cid, span) + self.const_eval_global_id(typing_env, cid, span) } // For errors during resolution, we deliberately do not point at the usage site of the constant, // since for these errors the place the constant is used shouldn't matter. @@ -105,7 +105,7 @@ impl<'tcx> TyCtxt<'tcx> { match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: None }; - self.const_eval_global_id_for_typeck(typing_env.param_env, cid, span).inspect(|_| { + self.const_eval_global_id_for_typeck(typing_env, cid, span).inspect(|_| { // We are emitting the lint here instead of in `is_const_evaluatable` // as we normalize obligations before checking them, and normalization // uses this function to evaluate this constant. @@ -144,24 +144,25 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_instance( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, instance: ty::Instance<'tcx>, span: Span, ) -> EvalToConstValueResult<'tcx> { - self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span) + self.const_eval_global_id(typing_env, GlobalId { instance, promoted: None }, span) } /// Evaluate a constant to a `ConstValue`. #[instrument(skip(self), level = "debug")] pub fn const_eval_global_id( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, cid: GlobalId<'tcx>, span: Span, ) -> EvalToConstValueResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); + let inputs = + self.erase_regions(typing_env.with_reveal_all_normalized(self).as_query_input(cid)); if !span.is_dummy() { // The query doesn't know where it is being invoked, so we need to fix the span. self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span)) @@ -174,13 +175,14 @@ impl<'tcx> TyCtxt<'tcx> { #[instrument(skip(self), level = "debug")] pub fn const_eval_global_id_for_typeck( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, cid: GlobalId<'tcx>, span: Span, ) -> EvalToValTreeResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); + let inputs = + self.erase_regions(typing_env.with_reveal_all_normalized(self).as_query_input(cid)); debug!(?inputs); if !span.is_dummy() { // The query doesn't know where it is being invoked, so we need to fix the span. @@ -202,12 +204,12 @@ impl<'tcx> TyCtxtEnsure<'tcx> { // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are // encountered. let args = GenericArgs::identity_for_item(self.tcx, def_id); - let instance = ty::Instance::new(def_id, args); + let instance = ty::Instance::new(def_id, self.tcx.erase_regions(args)); let cid = GlobalId { instance, promoted: None }; - let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx); + let typing_env = ty::TypingEnv::post_analysis(self.tcx, def_id); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.tcx.erase_regions(param_env.and(cid)); + let inputs = self.tcx.erase_regions(typing_env.as_query_input(cid)); self.eval_to_const_value_raw(inputs) } } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index d2fab8e78d5..8fd99303622 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -456,18 +456,6 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> { } } -impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { - type Cache = DefaultCache; - - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - self.value.default_span(tcx) - } - - fn ty_def_id(&self) -> Option { - self.value.ty_def_id() - } -} - impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { type Cache = DefaultCache; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b8291e8a352..9ae519dfe7e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1095,7 +1095,7 @@ rustc_queries! { /// Evaluates a constant and returns the computed allocation. /// /// **Do not use this** directly, use the `eval_to_const_value` or `eval_to_valtree` instead. - query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) + query eval_to_allocation_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) -> EvalToAllocationRawResult<'tcx> { desc { |tcx| "const-evaluating + checking `{}`", @@ -1121,7 +1121,7 @@ rustc_queries! { /// /// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`, /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`. - query eval_to_const_value_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) + query eval_to_const_value_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) -> EvalToConstValueResult<'tcx> { desc { |tcx| "simplifying constant for the type system `{}`", @@ -1133,7 +1133,7 @@ rustc_queries! { /// Evaluate a constant and convert it to a type level constant or /// return `None` if that is not possible. query eval_to_valtree( - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>> + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>> ) -> EvalToValTreeResult<'tcx> { desc { "evaluating type-level constant" } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index d42b6be4787..dab3e18de33 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -537,9 +537,7 @@ impl<'tcx> Instance<'tcx> { // All regions in the result of this query are erased, so it's // fine to erase all of the input regions. - let typing_env = tcx.erase_regions(typing_env); - let args = tcx.erase_regions(args); - tcx.resolve_instance_raw(typing_env.as_query_input((def_id, args))) + tcx.resolve_instance_raw(tcx.erase_regions(typing_env.as_query_input((def_id, args)))) } pub fn expect_resolve( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d1f8d1b0949..3078209a068 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1186,7 +1186,6 @@ impl<'tcx> TypingEnv<'tcx> { where T: TypeVisitable>, { - debug_assert!(!value.has_infer()); // FIXME(#132279): We should assert that the value does not contain any placeholders // as these placeholders are also local to the current inference context. However, we // currently use pseudo-canonical queries in the trait solver which replaces params with @@ -1209,7 +1208,7 @@ impl<'tcx> TypingEnv<'tcx> { /// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)` /// or by using `typing_env.as_query_input(value)`. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[derive(HashStable)] +#[derive(HashStable, TypeVisitable, TypeFoldable)] pub struct PseudoCanonicalInput<'tcx, T> { pub typing_env: TypingEnv<'tcx>, pub value: T, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 500515bc3cc..26480be29f3 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { map, tcx, local_decls: &body.local_decls, - ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine), typing_env, } } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 5150cb752bd..b3d9af37204 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -125,8 +125,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let mut state = - VnState::new(tcx, body, typing_env.param_env, &ssa, dominators, &body.local_decls); + let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls); ssa.for_each_assignment_mut( body.basic_blocks.as_mut_preserves_cfg(), |local, value, location| { @@ -266,7 +265,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn new( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ssa: &'body SsaLocals, dominators: Dominators, local_decls: &'body LocalDecls<'tcx>, @@ -280,7 +279,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { + 4 * body.basic_blocks.len(); VnState { tcx, - ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine), local_decls, locals: IndexVec::from_elem(None, local_decls), rev_locals: IndexVec::with_capacity(num_values), @@ -295,7 +294,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } fn typing_env(&self) -> ty::TypingEnv<'tcx> { - self.ecx.typing_env() + self.ecx.typing_env } #[instrument(level = "trace", skip(self), ret)] diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 71a843a785c..5c2c36db0f7 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -82,7 +82,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { let mut finder = TOFinder { tcx, typing_env, - ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine), body, arena, map: Map::new(tcx, body, Some(MAX_PLACES)), diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 67afd19aa73..53e282e9b46 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -183,7 +183,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // 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 can_const_prop = CanConstProp::check(tcx, typing_env, body); - let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env.param_env, DummyMachine); + let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env, DummyMachine); ConstPropagator { ecx, diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index b19adf321c3..9025b47c422 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::{ - GenericPredicates, Instance, List, ParamEnv, ScalarInt, TyCtxt, TypeVisitableExt, ValTree, + GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, ValTree, }; use rustc_middle::{mir, ty}; use rustc_span::def_id::LOCAL_CRATE; @@ -713,7 +713,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let instance = tables.instances[def]; let tcx = tables.tcx; let result = tcx.const_eval_instance( - ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), instance, tcx.def_span(instance.def_id()), ); diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 57fa4797c5e..5416e00fe0c 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -270,8 +270,8 @@ impl<'tcx> NonCopyConst<'tcx> { instance, promoted: None, }; - let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx); - let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, DUMMY_SP); + let typing_env = ty::TypingEnv::post_analysis(cx.tcx, def_id); + let result = cx.tcx.const_eval_global_id_for_typeck(typing_env, cid, DUMMY_SP); Self::is_value_unfrozen_raw(cx, result, ty) } @@ -294,7 +294,7 @@ impl<'tcx> NonCopyConst<'tcx> { instance, promoted: None, }; - tcx.const_eval_global_id_for_typeck(typing_env.param_env, cid, span) + tcx.const_eval_global_id_for_typeck(typing_env, cid, span) }, Ok(None) => Err(ErrorHandled::TooGeneric(span)), Err(err) => Err(ErrorHandled::Reported(err.into(), span)), diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index f46557ac630..9627447b342 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -70,7 +70,7 @@ impl NewPermission { access: None, protector: None, } - } else if pointee.is_unpin(*cx.tcx, cx.typing_env()) { + } else if pointee.is_unpin(*cx.tcx, cx.typing_env) { // A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`. NewPermission::Uniform { perm: Permission::Unique, @@ -128,7 +128,7 @@ impl NewPermission { fn from_box_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self { // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling). let pointee = ty.builtin_deref(true).unwrap(); - if pointee.is_unpin(*cx.tcx, cx.typing_env()) { + if pointee.is_unpin(*cx.tcx, cx.typing_env) { // A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only // a weak protector). NewPermission::Uniform { @@ -607,7 +607,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { match new_perm { NewPermission::Uniform { perm, .. } => write!(kind_str, "{perm:?} permission").unwrap(), - NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.typing_env()) => + NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.typing_env) => write!(kind_str, "{freeze_perm:?} permission").unwrap(), NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } => write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(), diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 8f8e29846c9..61a2e2bc8d9 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -131,8 +131,8 @@ impl<'tcx> NewPermission { kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>, ) -> Option { - let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env()); - let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env()); + let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env); + let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env); let is_protected = kind == RetagKind::FnEntry; // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`, // interior mutability and protectors interact poorly. @@ -163,10 +163,10 @@ impl<'tcx> NewPermission { zero_size: bool, ) -> Option { let pointee = ty.builtin_deref(true).unwrap(); - pointee.is_unpin(*cx.tcx, cx.typing_env()).then_some(()).map(|()| { + pointee.is_unpin(*cx.tcx, cx.typing_env).then_some(()).map(|()| { // Regular `Unpin` box, give it `noalias` but only a weak protector // because it is valid to deallocate it within the function. - let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.typing_env()); + let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.typing_env); let protected = kind == RetagKind::FnEntry; let initial_state = Permission::new_reserved(ty_is_freeze, protected); Self { @@ -520,7 +520,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Note: if we were to inline `new_reserved` below we would find out that // `ty_is_freeze` is eventually unused because it appears in a `ty_is_freeze || true`. // We are nevertheless including it here for clarity. - let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env()); + let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env); // Retag it. With protection! That is the entire point. let new_perm = NewPermission { initial_state: Permission::new_reserved(ty_is_freeze, /* protected */ true), diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 5ec497ef0ea..85591a0b370 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -273,7 +273,7 @@ pub fn create_ecx<'tcx>( let mut ecx = InterpCx::new( tcx, rustc_span::DUMMY_SP, - typing_env.param_env, + typing_env, MiriMachine::new(config, layout_cx) ); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 9c1951ec87a..3ab606e5847 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1128,7 +1128,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { let info = ecx.get_alloc_info(alloc_id); let def_ty = ecx.tcx.type_of(def_id).instantiate_identity(); let extern_decl_layout = ecx.tcx.layout_of( - ecx.typing_env().as_query_input(def_ty) + ecx.typing_env.as_query_input(def_ty) ).unwrap(); if extern_decl_layout.size != info.size || extern_decl_layout.align.abi != info.align { throw_unsup_format!( -- cgit 1.4.1-3-g733a5 From 002efeb72ac465cf04660537ca902172ab0e491b Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 19 Nov 2024 21:11:55 +0100 Subject: additional `TypingEnv` cleanups --- compiler/rustc_codegen_ssa/src/base.rs | 7 ++++--- compiler/rustc_hir_analysis/src/check/compare_impl_item.rs | 6 +++--- compiler/rustc_middle/src/mir/mod.rs | 5 +---- compiler/rustc_mir_transform/src/instsimplify.rs | 14 ++++---------- compiler/rustc_symbol_mangling/src/v0.rs | 6 +++--- compiler/rustc_trait_selection/src/traits/mod.rs | 4 ++-- compiler/rustc_trait_selection/src/traits/vtable.rs | 7 +++---- 7 files changed, 20 insertions(+), 29 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index c8b3b30218a..27c9cb0b31e 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -22,7 +22,7 @@ use rustc_middle::mir::BinOp; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_span::symbol::sym; @@ -119,7 +119,8 @@ pub fn validate_trivial_unsize<'tcx>( ) -> bool { match (source_data.principal(), target_data.principal()) { (Some(hr_source_principal), Some(hr_target_principal)) => { - let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized()); let universe = infcx.universe(); let ocx = ObligationCtxt::new(&infcx); infcx.enter_forall(hr_target_principal, |target_principal| { @@ -130,7 +131,7 @@ pub fn validate_trivial_unsize<'tcx>( ); let Ok(()) = ocx.eq_trace( &ObligationCause::dummy(), - ty::ParamEnv::reveal_all(), + param_env, ToTrace::to_trace( &ObligationCause::dummy(), hr_target_principal, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 77c324183c3..8a051e34f82 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1193,9 +1193,9 @@ fn compare_self_type<'tcx>( ty::AssocItemContainer::Trait => tcx.types.self_param, }; let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0); - let param_env = ty::ParamEnv::reveal_all(); - - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let (infcx, param_env) = tcx + .infer_ctxt() + .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, method.def_id)); let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty); match ExplicitSelf::determine(self_arg_ty, can_eq_self) { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 425cb059e57..e2379f282ec 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -459,10 +459,7 @@ impl<'tcx> Body<'tcx> { typing_mode: ty::TypingMode::non_body_analysis(), param_env: tcx.param_env(self.source.def_id()), }, - MirPhase::Runtime(_) => TypingEnv { - typing_mode: ty::TypingMode::PostAnalysis, - param_env: tcx.param_env_reveal_all_normalized(self.source.def_id()), - }, + MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()), } } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index b80abcca969..3352d583f2c 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -6,7 +6,7 @@ use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::mir::*; use rustc_middle::ty::layout::ValidityRequirement; -use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, layout}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout}; use rustc_span::sym; use rustc_span::symbol::Symbol; @@ -34,7 +34,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { let ctx = InstSimplifyContext { tcx, local_decls: &body.local_decls, - param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()), + typing_env: body.typing_env(tcx), }; let preserve_ub_checks = attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks); @@ -66,13 +66,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { struct InstSimplifyContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, local_decls: &'a LocalDecls<'tcx>, - param_env: ParamEnv<'tcx>, -} - -impl<'tcx> InstSimplifyContext<'_, 'tcx> { - fn typing_env(&self) -> ty::TypingEnv<'tcx> { - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } - } + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> InstSimplifyContext<'_, 'tcx> { @@ -354,7 +348,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } let known_is_valid = - intrinsic_assert_panics(self.tcx, self.typing_env(), args[0], intrinsic_name); + intrinsic_assert_panics(self.tcx, self.typing_env, args[0], intrinsic_name); match known_is_valid { // We don't know the layout or it's not validity assertion at all, don't touch it None => {} diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 94f51b87cff..dcbc5f0f76d 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -233,11 +233,11 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { let key = self.tcx.def_key(impl_def_id); let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; - let mut param_env = self.tcx.param_env_reveal_all_normalized(impl_def_id); + let mut typing_env = ty::TypingEnv::post_analysis(self.tcx, impl_def_id); if !args.is_empty() { - param_env = EarlyBinder::bind(param_env).instantiate(self.tcx, args); + typing_env.param_env = + EarlyBinder::bind(typing_env.param_env).instantiate(self.tcx, args); } - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; match &mut impl_trait_ref { Some(impl_trait_ref) => { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index c0603c06d42..80cef690028 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -698,8 +698,8 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( /// used during analysis. pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec>) -> bool { debug!("impossible_predicates(predicates={:?})", predicates); - let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); - let param_env = ty::ParamEnv::reveal_all(); + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized()); let ocx = ObligationCtxt::new(&infcx); let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates); for predicate in predicates { diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 8352d31d13a..b5bc8364c7b 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -9,8 +9,7 @@ use rustc_infer::traits::util::PredicateSet; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, - VtblEntry, + self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry, }; use rustc_span::{DUMMY_SP, Span, sym}; use smallvec::{SmallVec, smallvec}; @@ -442,8 +441,8 @@ fn trait_refs_are_compatible<'tcx>( return false; } - let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); - let param_env = ty::ParamEnv::reveal_all(); + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized()); let ocx = ObligationCtxt::new(&infcx); let hr_source_principal = ocx.normalize(&ObligationCause::dummy(), param_env, hr_vtable_principal); -- cgit 1.4.1-3-g733a5 From d04088fa366f5a764ba3b5055450db083b4406b2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 20 Nov 2024 11:05:53 +0100 Subject: interpret: make typing_env field private --- compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 5 ++--- compiler/rustc_const_eval/src/const_eval/machine.rs | 4 ++-- compiler/rustc_const_eval/src/interpret/eval_context.rs | 4 ++-- compiler/rustc_mir_transform/src/gvn.rs | 4 ++-- src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs | 7 ++++--- src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs | 11 ++++++----- src/tools/miri/src/machine.rs | 9 +++++---- 7 files changed, 23 insertions(+), 21 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 64331eea75c..647d880e2bf 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -7,7 +7,7 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo}; use rustc_middle::mir::{self, ConstAlloc, ConstValue}; use rustc_middle::query::TyCtxtAt; -use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; @@ -30,7 +30,6 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( cid: GlobalId<'tcx>, body: &'tcx mir::Body<'tcx>, ) -> InterpResult<'tcx, R> { - trace!(?ecx.typing_env); let tcx = *ecx.tcx; assert!( cid.promoted.is_some() @@ -220,7 +219,7 @@ pub(super) fn op_to_const<'tcx>( let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs debug_assert!( matches!( - ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env).kind(), + ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(), ty::Str | ty::Slice(..), ), "`ConstValue::Slice` is for slice-tailed types only, but got {}", diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index db82050c73c..b27e3606f38 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem}; use rustc_middle::mir::AssertMessage; use rustc_middle::query::TyCtxtAt; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::Span; @@ -667,7 +667,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { .is_some_and(|p| !p.immutable()) { // That next check is expensive, that's why we have all the guards above. - let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env); + let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env()); let place = ecx.ref_to_mplace(val)?; let new_place = if is_immutable { place.map_provenance(CtfeProvenance::as_immutable) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 42fdf32e91e..fe93a48c2f2 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -39,8 +39,8 @@ pub struct InterpCx<'tcx, M: Machine<'tcx>> { pub tcx: TyCtxtAt<'tcx>, /// The current context in case we're evaluating in a - /// polymorphic context. This always uses `ty::TypingMode::PostAnalysis` - pub typing_env: ty::TypingEnv<'tcx>, + /// polymorphic context. This always uses `ty::TypingMode::PostAnalysis`. + pub(super) typing_env: ty::TypingEnv<'tcx>, /// The virtual memory system. pub memory: Memory<'tcx, M>, diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index b3d9af37204..976f4a8e919 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -100,7 +100,7 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::GlobalAlloc; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; @@ -294,7 +294,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } fn typing_env(&self) -> ty::TypingEnv<'tcx> { - self.ecx.typing_env + self.ecx.typing_env() } #[instrument(level = "trace", skip(self), ret)] diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 9627447b342..a855603eeb3 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -12,6 +12,7 @@ use std::{cmp, mem}; use rustc_abi::{BackendRepr, Size}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Mutability, RetagKind}; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use self::diagnostics::{RetagCause, RetagInfo}; @@ -70,7 +71,7 @@ impl NewPermission { access: None, protector: None, } - } else if pointee.is_unpin(*cx.tcx, cx.typing_env) { + } else if pointee.is_unpin(*cx.tcx, cx.typing_env()) { // A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`. NewPermission::Uniform { perm: Permission::Unique, @@ -128,7 +129,7 @@ impl NewPermission { fn from_box_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self { // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling). let pointee = ty.builtin_deref(true).unwrap(); - if pointee.is_unpin(*cx.tcx, cx.typing_env) { + if pointee.is_unpin(*cx.tcx, cx.typing_env()) { // A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only // a weak protector). NewPermission::Uniform { @@ -607,7 +608,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { match new_perm { NewPermission::Uniform { perm, .. } => write!(kind_str, "{perm:?} permission").unwrap(), - NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.typing_env) => + NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.typing_env()) => write!(kind_str, "{freeze_perm:?} permission").unwrap(), NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } => write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(), diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 61a2e2bc8d9..8469744bbc4 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,5 +1,6 @@ use rustc_abi::{BackendRepr, Size}; use rustc_middle::mir::{Mutability, RetagKind}; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use rustc_span::def_id::DefId; @@ -131,8 +132,8 @@ impl<'tcx> NewPermission { kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>, ) -> Option { - let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env); - let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env); + let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env()); + let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env()); let is_protected = kind == RetagKind::FnEntry; // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`, // interior mutability and protectors interact poorly. @@ -163,10 +164,10 @@ impl<'tcx> NewPermission { zero_size: bool, ) -> Option { let pointee = ty.builtin_deref(true).unwrap(); - pointee.is_unpin(*cx.tcx, cx.typing_env).then_some(()).map(|()| { + pointee.is_unpin(*cx.tcx, cx.typing_env()).then_some(()).map(|()| { // Regular `Unpin` box, give it `noalias` but only a weak protector // because it is valid to deallocate it within the function. - let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.typing_env); + let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.typing_env()); let protected = kind == RetagKind::FnEntry; let initial_state = Permission::new_reserved(ty_is_freeze, protected); Self { @@ -520,7 +521,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Note: if we were to inline `new_reserved` below we would find out that // `ty_is_freeze` is eventually unused because it appears in a `ty_is_freeze || true`. // We are nevertheless including it here for clarity. - let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env); + let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env()); // Retag it. With protection! That is the entire point. let new_perm = NewPermission { initial_state: Permission::new_reserved(ty_is_freeze, /* protected */ true), diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 3ab606e5847..7b03aed4763 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -17,7 +17,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::static_assert_size; use rustc_middle::mir; use rustc_middle::query::TyCtxtAt; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{ + HasTyCtxt, HasTypingEnv, LayoutCx, LayoutError, LayoutOf, TyAndLayout, +}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::config::InliningThreshold; use rustc_span::def_id::{CrateNum, DefId}; @@ -1127,9 +1129,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { }; let info = ecx.get_alloc_info(alloc_id); let def_ty = ecx.tcx.type_of(def_id).instantiate_identity(); - let extern_decl_layout = ecx.tcx.layout_of( - ecx.typing_env.as_query_input(def_ty) - ).unwrap(); + let extern_decl_layout = + ecx.tcx.layout_of(ecx.typing_env().as_query_input(def_ty)).unwrap(); if extern_decl_layout.size != info.size || extern_decl_layout.align.abi != info.align { throw_unsup_format!( "extern static `{link_name}` has been declared as `{krate}::{name}` \ -- cgit 1.4.1-3-g733a5 From 297b618944d4619a1990b1992d9142c6cf893dc6 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Mon, 2 Sep 2024 01:13:07 +0800 Subject: reduce false positives of tail-expr-drop-order from consumed values take 2 open up coroutines tweak the wordings the lint works up until 2021 We were missing one case, for ADTs, which was causing `Result` to yield incorrect results. only include field spans with significant types deduplicate and eliminate field spans switch to emit spans to impl Drops Co-authored-by: Niko Matsakis collect drops instead of taking liveness diff apply some suggestions and add explantory notes small fix on the cache let the query recurse through coroutine new suggestion format with extracted variable name fine-tune the drop span and messages bugfix on runtime borrows tweak message wording filter out ecosystem types earlier apply suggestions clippy check lint level at session level further restrict applicability of the lint translate bid into nop for stable mir detect cycle in type structure --- compiler/rustc_borrowck/src/dataflow.rs | 1 + compiler/rustc_borrowck/src/lib.rs | 2 + .../src/polonius/loan_invalidations.rs | 1 + compiler/rustc_borrowck/src/type_check/mod.rs | 1 + compiler/rustc_codegen_cranelift/src/base.rs | 1 + compiler/rustc_codegen_cranelift/src/constant.rs | 1 + compiler/rustc_codegen_ssa/src/mir/statement.rs | 1 + .../rustc_const_eval/src/check_consts/check.rs | 1 + compiler/rustc_const_eval/src/interpret/step.rs | 3 + compiler/rustc_hir_analysis/src/check/region.rs | 20 +- compiler/rustc_index/src/bit_set.rs | 140 +++- compiler/rustc_lint/messages.ftl | 3 - compiler/rustc_lint/src/lib.rs | 3 - compiler/rustc_lint/src/tail_expr_drop_order.rs | 308 --------- compiler/rustc_lint_defs/src/builtin.rs | 78 +++ compiler/rustc_middle/src/middle/region.rs | 5 + compiler/rustc_middle/src/mir/pretty.rs | 5 + compiler/rustc_middle/src/mir/syntax.rs | 28 + compiler/rustc_middle/src/mir/visit.rs | 1 + compiler/rustc_middle/src/query/keys.rs | 8 + compiler/rustc_middle/src/query/mod.rs | 22 + compiler/rustc_middle/src/thir.rs | 17 +- compiler/rustc_middle/src/ty/rvalue_scopes.rs | 27 +- .../rustc_mir_build/src/build/expr/as_operand.rs | 23 +- .../rustc_mir_build/src/build/expr/as_place.rs | 3 +- .../rustc_mir_build/src/build/expr/as_rvalue.rs | 14 +- compiler/rustc_mir_build/src/build/expr/as_temp.rs | 21 +- compiler/rustc_mir_build/src/build/expr/into.rs | 18 +- compiler/rustc_mir_build/src/build/expr/stmt.rs | 13 +- compiler/rustc_mir_build/src/build/matches/mod.rs | 13 +- compiler/rustc_mir_build/src/build/scope.rs | 93 ++- compiler/rustc_mir_build/src/thir/cx/expr.rs | 69 +- compiler/rustc_mir_dataflow/src/impls/liveness.rs | 1 + .../src/impls/storage_liveness.rs | 1 + .../rustc_mir_dataflow/src/move_paths/builder.rs | 1 + compiler/rustc_mir_transform/messages.ftl | 25 + compiler/rustc_mir_transform/src/coroutine.rs | 1 + .../src/coverage/spans/from_mir.rs | 1 + .../rustc_mir_transform/src/dataflow_const_prop.rs | 3 +- .../src/dead_store_elimination.rs | 3 +- compiler/rustc_mir_transform/src/dest_prop.rs | 5 +- compiler/rustc_mir_transform/src/jump_threading.rs | 1 + compiler/rustc_mir_transform/src/lib.rs | 2 + .../src/lint_tail_expr_drop_order.rs | 701 +++++++++++++++++++++ .../src/remove_noop_landing_pads.rs | 1 + compiler/rustc_mir_transform/src/remove_zsts.rs | 1 + compiler/rustc_mir_transform/src/simplify.rs | 18 +- compiler/rustc_mir_transform/src/validate.rs | 2 + compiler/rustc_smir/src/rustc_smir/convert/mir.rs | 4 + compiler/rustc_ty_utils/src/needs_drop.rs | 68 +- .../clippy_utils/src/qualify_min_const_fn.rs | 1 + tests/ui/drop/lint-tail-expr-drop-order-gated.rs | 7 +- tests/ui/drop/lint-tail-expr-drop-order.rs | 215 ++++++- tests/ui/drop/lint-tail-expr-drop-order.stderr | 327 +++++++++- tests/ui/thir-print/thir-flat-const-variant.stdout | 162 +++-- tests/ui/thir-print/thir-flat.stdout | 18 +- tests/ui/thir-print/thir-tree-match.stdout | 28 +- tests/ui/thir-print/thir-tree.stdout | 4 +- 58 files changed, 2011 insertions(+), 534 deletions(-) delete mode 100644 compiler/rustc_lint/src/tail_expr_drop_order.rs create mode 100644 compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 7adc7a8863e..452038bc328 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -641,6 +641,7 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { | mir::StatementKind::Coverage(..) | mir::StatementKind::Intrinsic(..) | mir::StatementKind::ConstEvalCounter + | mir::StatementKind::BackwardIncompatibleDropHint { .. } | mir::StatementKind::Nop => {} } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 03f7b05d1e3..16a4f699177 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -652,6 +652,8 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt< | StatementKind::Coverage(..) // These do not actually affect borrowck | StatementKind::ConstEvalCounter + // This do not affect borrowck + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::StorageLive(..) => {} StatementKind::StorageDead(local) => { self.access_place( diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index d1b65943199..f646beeecf7 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -88,6 +88,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { | StatementKind::Nop | StatementKind::Retag { .. } | StatementKind::Deinit(..) + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::SetDiscriminant { .. } => { bug!("Statement not allowed in this MIR phase") } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index c6b34d5bf1d..3a7ed711f68 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1252,6 +1252,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | StatementKind::Coverage(..) | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => {} StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => { bug!("Statement not allowed in this MIR phase") diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 77ee9773940..70b7d92ce15 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -924,6 +924,7 @@ fn codegen_stmt<'tcx>( | StatementKind::FakeRead(..) | StatementKind::Retag { .. } | StatementKind::PlaceMention(..) + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::AscribeUserType(..) => {} StatementKind::Coverage { .. } => unreachable!(), diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 5311547309c..abe6085b04f 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -583,6 +583,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( | StatementKind::PlaceMention(..) | StatementKind::Coverage(_) | StatementKind::ConstEvalCounter + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => {} } } diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 1681ea1de5f..cd55a838a75 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -92,6 +92,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::ConstEvalCounter | mir::StatementKind::PlaceMention(..) + | mir::StatementKind::BackwardIncompatibleDropHint { .. } | mir::StatementKind::Nop => {} } } diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 8e96d365beb..1129b5caec5 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -609,6 +609,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => {} } } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 98aca37e73e..b61865be667 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -143,6 +143,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Defined to do nothing. These are added by optimization passes, to avoid changing the // size of MIR constantly. Nop => {} + + // Only used for temporary lifetime lints + BackwardIncompatibleDropHint { .. } => {} } interp_ok(()) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 679f6ccb816..b9cb48cafdc 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -17,6 +17,7 @@ use rustc_index::Idx; use rustc_middle::bug; use rustc_middle::middle::region::*; use rustc_middle::ty::TyCtxt; +use rustc_session::lint; use rustc_span::source_map; use tracing::debug; @@ -167,8 +168,23 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h } } if let Some(tail_expr) = blk.expr { - if blk.span.edition().at_least_rust_2024() { - visitor.terminating_scopes.insert(tail_expr.hir_id.local_id); + let local_id = tail_expr.hir_id.local_id; + let edition = blk.span.edition(); + if edition.at_least_rust_2024() { + visitor.terminating_scopes.insert(local_id); + } else if !visitor + .tcx + .lints_that_dont_need_to_run(()) + .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER)) + { + // If this temporary scope will be changing once the codebase adopts Rust 2024, + // and we are linting about possible semantic changes that would result, + // then record this node-id in the field `backwards_incompatible_scope` + // for future reference. + visitor + .scope_tree + .backwards_incompatible_scope + .insert(local_id, Scope { id: local_id, data: ScopeData::Node }); } visitor.visit_expr(tail_expr); } diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index c2b9cae680b..a9239489222 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -460,6 +460,10 @@ impl ChunkedBitSet { self.chunks.iter().map(|chunk| chunk.count()).sum() } + pub fn is_empty(&self) -> bool { + self.chunks.iter().all(|chunk| matches!(chunk, Chunk::Zeros(..) | Chunk::Ones(0))) + } + /// Returns `true` if `self` contains `elem`. #[inline] pub fn contains(&self, elem: T) -> bool { @@ -668,12 +672,140 @@ impl BitRelations> for ChunkedBitSet { changed } - fn subtract(&mut self, _other: &ChunkedBitSet) -> bool { - unimplemented!("implement if/when necessary"); + fn subtract(&mut self, other: &ChunkedBitSet) -> bool { + assert_eq!(self.domain_size, other.domain_size); + debug_assert_eq!(self.chunks.len(), other.chunks.len()); + + let mut changed = false; + for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) { + match (&mut self_chunk, &other_chunk) { + (Zeros(..), _) | (_, Zeros(..)) => {} + ( + Ones(self_chunk_domain_size) | Mixed(self_chunk_domain_size, _, _), + Ones(other_chunk_domain_size), + ) => { + debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size); + changed = true; + *self_chunk = Zeros(*self_chunk_domain_size); + } + ( + Ones(self_chunk_domain_size), + Mixed(other_chunk_domain_size, other_chunk_count, other_chunk_words), + ) => { + debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size); + changed = true; + let num_words = num_words(*self_chunk_domain_size as usize); + debug_assert!(num_words > 0 && num_words <= CHUNK_WORDS); + let mut tail_mask = + 1 << (*other_chunk_domain_size - ((num_words - 1) * WORD_BITS) as u16) - 1; + let mut self_chunk_words = **other_chunk_words; + for word in self_chunk_words[0..num_words].iter_mut().rev() { + *word = !*word & tail_mask; + tail_mask = u64::MAX; + } + let self_chunk_count = *self_chunk_domain_size - *other_chunk_count; + debug_assert_eq!( + self_chunk_count, + self_chunk_words[0..num_words] + .iter() + .map(|w| w.count_ones() as ChunkSize) + .sum() + ); + *self_chunk = + Mixed(*self_chunk_domain_size, self_chunk_count, Rc::new(self_chunk_words)); + } + ( + Mixed( + self_chunk_domain_size, + ref mut self_chunk_count, + ref mut self_chunk_words, + ), + Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words), + ) => { + // See [`>>::union`] for the explanation + let op = |a: u64, b: u64| a & !b; + let num_words = num_words(*self_chunk_domain_size as usize); + if bitwise_changes( + &self_chunk_words[0..num_words], + &other_chunk_words[0..num_words], + op, + ) { + let self_chunk_words = Rc::make_mut(self_chunk_words); + let has_changed = bitwise( + &mut self_chunk_words[0..num_words], + &other_chunk_words[0..num_words], + op, + ); + debug_assert!(has_changed); + *self_chunk_count = self_chunk_words[0..num_words] + .iter() + .map(|w| w.count_ones() as ChunkSize) + .sum(); + if *self_chunk_count == 0 { + *self_chunk = Zeros(*self_chunk_domain_size); + } + changed = true; + } + } + } + } + changed } - fn intersect(&mut self, _other: &ChunkedBitSet) -> bool { - unimplemented!("implement if/when necessary"); + fn intersect(&mut self, other: &ChunkedBitSet) -> bool { + assert_eq!(self.domain_size, other.domain_size); + debug_assert_eq!(self.chunks.len(), other.chunks.len()); + + let mut changed = false; + for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) { + match (&mut self_chunk, &other_chunk) { + (Zeros(..), _) | (_, Ones(..)) => {} + ( + Ones(self_chunk_domain_size), + Zeros(other_chunk_domain_size) | Mixed(other_chunk_domain_size, ..), + ) + | (Mixed(self_chunk_domain_size, ..), Zeros(other_chunk_domain_size)) => { + debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size); + changed = true; + *self_chunk = other_chunk.clone(); + } + ( + Mixed( + self_chunk_domain_size, + ref mut self_chunk_count, + ref mut self_chunk_words, + ), + Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words), + ) => { + // See [`>>::union`] for the explanation + let op = |a, b| a & b; + let num_words = num_words(*self_chunk_domain_size as usize); + if bitwise_changes( + &self_chunk_words[0..num_words], + &other_chunk_words[0..num_words], + op, + ) { + let self_chunk_words = Rc::make_mut(self_chunk_words); + let has_changed = bitwise( + &mut self_chunk_words[0..num_words], + &other_chunk_words[0..num_words], + op, + ); + debug_assert!(has_changed); + *self_chunk_count = self_chunk_words[0..num_words] + .iter() + .map(|w| w.count_ones() as ChunkSize) + .sum(); + if *self_chunk_count == 0 { + *self_chunk = Zeros(*self_chunk_domain_size); + } + changed = true; + } + } + } + } + + changed } } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 6e35d89b488..69fd7f2d8b2 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -772,9 +772,6 @@ lint_suspicious_double_ref_clone = lint_suspicious_double_ref_deref = using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type -lint_tail_expr_drop_order = these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 - .label = these values have significant drop implementation and will observe changes in drop order under Edition 2024 - lint_trailing_semi_macro = trailing semicolon in macro used in expression position .note1 = macro invocations at the end of a block are treated as expressions .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}` diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 86112277504..4cf5c7b4ff9 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -75,7 +75,6 @@ mod redundant_semicolon; mod reference_casting; mod shadowed_into_iter; mod static_mut_refs; -mod tail_expr_drop_order; mod traits; mod types; mod unit_bindings; @@ -116,7 +115,6 @@ use rustc_middle::ty::TyCtxt; use shadowed_into_iter::ShadowedIntoIter; pub use shadowed_into_iter::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER}; use static_mut_refs::*; -use tail_expr_drop_order::TailExprDropOrder; use traits::*; use types::*; use unit_bindings::*; @@ -240,7 +238,6 @@ late_lint_methods!( AsyncFnInTrait: AsyncFnInTrait, NonLocalDefinitions: NonLocalDefinitions::default(), ImplTraitOvercaptures: ImplTraitOvercaptures, - TailExprDropOrder: TailExprDropOrder, IfLetRescope: IfLetRescope::default(), StaticMutRefs: StaticMutRefs, UnqualifiedLocalImports: UnqualifiedLocalImports, diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs deleted file mode 100644 index 19763ce1ec5..00000000000 --- a/compiler/rustc_lint/src/tail_expr_drop_order.rs +++ /dev/null @@ -1,308 +0,0 @@ -use std::mem::swap; - -use rustc_ast::UnOp; -use rustc_hir::def::Res; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, Block, Expr, ExprKind, LetStmt, Pat, PatKind, QPath, StmtKind}; -use rustc_macros::LintDiagnostic; -use rustc_middle::ty; -use rustc_session::lint::FutureIncompatibilityReason; -use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::Span; -use rustc_span::edition::Edition; - -use crate::{LateContext, LateLintPass}; - -declare_lint! { - /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location, - /// that runs a custom `Drop` destructor. - /// Some of them may be dropped earlier in Edition 2024 that they used to in Edition 2021 and prior. - /// This lint detects those cases and provides you information on those values and their custom destructor implementations. - /// Your discretion on this information is required. - /// - /// ### Example - /// ```rust,edition2021 - /// #![warn(tail_expr_drop_order)] - /// struct Droppy(i32); - /// impl Droppy { - /// fn get(&self) -> i32 { - /// self.0 - /// } - /// } - /// impl Drop for Droppy { - /// fn drop(&mut self) { - /// // This is a custom destructor and it induces side-effects that is observable - /// // especially when the drop order at a tail expression changes. - /// println!("loud drop {}", self.0); - /// } - /// } - /// fn edition_2021() -> i32 { - /// let another_droppy = Droppy(0); - /// Droppy(1).get() - /// } - /// fn main() { - /// edition_2021(); - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// In tail expression of blocks or function bodies, - /// values of type with significant `Drop` implementation has an ill-specified drop order - /// before Edition 2024 so that they are dropped only after dropping local variables. - /// Edition 2024 introduces a new rule with drop orders for them, - /// so that they are dropped first before dropping local variables. - /// - /// A significant `Drop::drop` destructor here refers to an explicit, arbitrary - /// implementation of the `Drop` trait on the type, with exceptions including `Vec`, - /// `Box`, `Rc`, `BTreeMap` and `HashMap` that are marked by the compiler otherwise - /// so long that the generic types have no significant destructor recursively. - /// In other words, a type has a significant drop destructor when it has a `Drop` implementation - /// or its destructor invokes a significant destructor on a type. - /// Since we cannot completely reason about the change by just inspecting the existence of - /// a significant destructor, this lint remains only a suggestion and is set to `allow` by default. - /// - /// This lint only points out the issue with `Droppy`, which will be dropped before `another_droppy` - /// does in Edition 2024. - /// No fix will be proposed by this lint. - /// However, the most probable fix is to hoist `Droppy` into its own local variable binding. - /// ```rust - /// struct Droppy(i32); - /// impl Droppy { - /// fn get(&self) -> i32 { - /// self.0 - /// } - /// } - /// fn edition_2024() -> i32 { - /// let value = Droppy(0); - /// let another_droppy = Droppy(1); - /// value.get() - /// } - /// ``` - pub TAIL_EXPR_DROP_ORDER, - Allow, - "Detect and warn on significant change in drop order in tail expression location", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), - reference: "issue #123739 ", - }; -} - -declare_lint_pass!(TailExprDropOrder => [TAIL_EXPR_DROP_ORDER]); - -impl TailExprDropOrder { - fn check_fn_or_closure<'tcx>( - cx: &LateContext<'tcx>, - fn_kind: hir::intravisit::FnKind<'tcx>, - body: &'tcx hir::Body<'tcx>, - def_id: rustc_span::def_id::LocalDefId, - ) { - let mut locals = vec![]; - if matches!(fn_kind, hir::intravisit::FnKind::Closure) { - for &capture in cx.tcx.closure_captures(def_id) { - if matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue) - && capture.place.ty().has_significant_drop(cx.tcx, cx.typing_env()) - { - locals.push(capture.var_ident.span); - } - } - } - for param in body.params { - if cx - .typeck_results() - .node_type(param.hir_id) - .has_significant_drop(cx.tcx, cx.typing_env()) - { - locals.push(param.span); - } - } - if let hir::ExprKind::Block(block, _) = body.value.kind { - LintVisitor { cx, locals }.check_block_inner(block); - } else { - LintTailExpr { cx, locals: &locals, is_root_tail_expr: true }.visit_expr(body.value); - } - } -} - -impl<'tcx> LateLintPass<'tcx> for TailExprDropOrder { - fn check_fn( - &mut self, - cx: &LateContext<'tcx>, - fn_kind: hir::intravisit::FnKind<'tcx>, - _: &'tcx hir::FnDecl<'tcx>, - body: &'tcx hir::Body<'tcx>, - _: Span, - def_id: rustc_span::def_id::LocalDefId, - ) { - if !body.value.span.edition().at_least_rust_2024() { - Self::check_fn_or_closure(cx, fn_kind, body, def_id); - } - } -} - -struct LintVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - // We only record locals that have significant drops - locals: Vec, -} - -struct LocalCollector<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - locals: &'a mut Vec, -} - -impl<'a, 'tcx> Visitor<'tcx> for LocalCollector<'a, 'tcx> { - type Result = (); - fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) { - if let PatKind::Binding(_binding_mode, id, ident, pat) = pat.kind { - let ty = self.cx.typeck_results().node_type(id); - if ty.has_significant_drop(self.cx.tcx, self.cx.typing_env()) { - self.locals.push(ident.span); - } - if let Some(pat) = pat { - self.visit_pat(pat); - } - } else { - intravisit::walk_pat(self, pat); - } - } -} - -impl<'a, 'tcx> Visitor<'tcx> for LintVisitor<'a, 'tcx> { - fn visit_block(&mut self, block: &'tcx Block<'tcx>) { - let mut locals = <_>::default(); - swap(&mut locals, &mut self.locals); - self.check_block_inner(block); - swap(&mut locals, &mut self.locals); - } - fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) { - LocalCollector { cx: self.cx, locals: &mut self.locals }.visit_local(local); - } -} - -impl<'a, 'tcx> LintVisitor<'a, 'tcx> { - fn check_block_inner(&mut self, block: &Block<'tcx>) { - if block.span.at_least_rust_2024() { - // We only lint up to Edition 2021 - return; - } - let Some(tail_expr) = block.expr else { return }; - for stmt in block.stmts { - match stmt.kind { - StmtKind::Let(let_stmt) => self.visit_local(let_stmt), - StmtKind::Item(_) => {} - StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), - } - } - if self.locals.is_empty() { - return; - } - LintTailExpr { cx: self.cx, locals: &self.locals, is_root_tail_expr: true } - .visit_expr(tail_expr); - } -} - -struct LintTailExpr<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - is_root_tail_expr: bool, - locals: &'a [Span], -} - -impl<'a, 'tcx> LintTailExpr<'a, 'tcx> { - fn expr_eventually_point_into_local(mut expr: &Expr<'tcx>) -> bool { - loop { - match expr.kind { - ExprKind::Index(access, _, _) | ExprKind::Field(access, _) => expr = access, - ExprKind::AddrOf(_, _, referee) | ExprKind::Unary(UnOp::Deref, referee) => { - expr = referee - } - ExprKind::Path(_) - if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind - && let [local, ..] = path.segments - && let Res::Local(_) = local.res => - { - return true; - } - _ => return false, - } - } - } - - fn expr_generates_nonlocal_droppy_value(&self, expr: &Expr<'tcx>) -> bool { - if Self::expr_eventually_point_into_local(expr) { - return false; - } - self.cx - .typeck_results() - .expr_ty(expr) - .has_significant_drop(self.cx.tcx, self.cx.typing_env()) - } -} - -impl<'a, 'tcx> Visitor<'tcx> for LintTailExpr<'a, 'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - if self.is_root_tail_expr { - self.is_root_tail_expr = false; - } else if self.expr_generates_nonlocal_droppy_value(expr) { - self.cx.tcx.emit_node_span_lint( - TAIL_EXPR_DROP_ORDER, - expr.hir_id, - expr.span, - TailExprDropOrderLint { spans: self.locals.to_vec() }, - ); - return; - } - match expr.kind { - ExprKind::Match(scrutinee, _, _) => self.visit_expr(scrutinee), - - ExprKind::ConstBlock(_) - | ExprKind::Array(_) - | ExprKind::Break(_, _) - | ExprKind::Continue(_) - | ExprKind::Ret(_) - | ExprKind::Become(_) - | ExprKind::Yield(_, _) - | ExprKind::InlineAsm(_) - | ExprKind::If(_, _, _) - | ExprKind::Loop(_, _, _, _) - | ExprKind::Closure(_) - | ExprKind::DropTemps(_) - | ExprKind::OffsetOf(_, _) - | ExprKind::Assign(_, _, _) - | ExprKind::AssignOp(_, _, _) - | ExprKind::Lit(_) - | ExprKind::Err(_) => {} - - ExprKind::MethodCall(_, _, _, _) - | ExprKind::Call(_, _) - | ExprKind::Type(_, _) - | ExprKind::Tup(_) - | ExprKind::Binary(_, _, _) - | ExprKind::Unary(_, _) - | ExprKind::Path(_) - | ExprKind::Let(_) - | ExprKind::Cast(_, _) - | ExprKind::Field(_, _) - | ExprKind::Index(_, _, _) - | ExprKind::AddrOf(_, _, _) - | ExprKind::Struct(_, _, _) - | ExprKind::Repeat(_, _) => intravisit::walk_expr(self, expr), - - ExprKind::Block(_, _) => { - // We do not lint further because the drop order stays the same inside the block - } - } - } - fn visit_block(&mut self, block: &'tcx Block<'tcx>) { - LintVisitor { cx: self.cx, locals: <_>::default() }.check_block_inner(block); - } -} - -#[derive(LintDiagnostic)] -#[diag(lint_tail_expr_drop_order)] -struct TailExprDropOrderLint { - #[label] - pub spans: Vec, -} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 313a7badf19..9036741e078 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -101,6 +101,7 @@ declare_lint_pass! { SINGLE_USE_LIFETIMES, SOFT_UNSTABLE, STABLE_FEATURES, + TAIL_EXPR_DROP_ORDER, TEST_UNSTABLE_LINT, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, TRIVIAL_CASTS, @@ -4994,6 +4995,83 @@ declare_lint! { "detects pointer to integer transmutes in const functions and associated constants", } +declare_lint! { + /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location, + /// that runs a custom `Drop` destructor. + /// Some of them may be dropped earlier in Edition 2024 that they used to in Edition 2021 and prior. + /// This lint detects those cases and provides you information on those values and their custom destructor implementations. + /// Your discretion on this information is required. + /// + /// ### Example + /// ```rust,edition2021 + /// #![warn(tail_expr_drop_order)] + /// struct Droppy(i32); + /// impl Droppy { + /// fn get(&self) -> i32 { + /// self.0 + /// } + /// } + /// impl Drop for Droppy { + /// fn drop(&mut self) { + /// // This is a custom destructor and it induces side-effects that is observable + /// // especially when the drop order at a tail expression changes. + /// println!("loud drop {}", self.0); + /// } + /// } + /// fn edition_2021() -> i32 { + /// let another_droppy = Droppy(0); + /// Droppy(1).get() + /// } + /// fn main() { + /// edition_2021(); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// In tail expression of blocks or function bodies, + /// values of type with significant `Drop` implementation has an ill-specified drop order + /// before Edition 2024 so that they are dropped only after dropping local variables. + /// Edition 2024 introduces a new rule with drop orders for them, + /// so that they are dropped first before dropping local variables. + /// + /// A significant `Drop::drop` destructor here refers to an explicit, arbitrary + /// implementation of the `Drop` trait on the type, with exceptions including `Vec`, + /// `Box`, `Rc`, `BTreeMap` and `HashMap` that are marked by the compiler otherwise + /// so long that the generic types have no significant destructor recursively. + /// In other words, a type has a significant drop destructor when it has a `Drop` implementation + /// or its destructor invokes a significant destructor on a type. + /// Since we cannot completely reason about the change by just inspecting the existence of + /// a significant destructor, this lint remains only a suggestion and is set to `allow` by default. + /// + /// This lint only points out the issue with `Droppy`, which will be dropped before `another_droppy` + /// does in Edition 2024. + /// No fix will be proposed by this lint. + /// However, the most probable fix is to hoist `Droppy` into its own local variable binding. + /// ```rust + /// struct Droppy(i32); + /// impl Droppy { + /// fn get(&self) -> i32 { + /// self.0 + /// } + /// } + /// fn edition_2024() -> i32 { + /// let value = Droppy(0); + /// let another_droppy = Droppy(1); + /// value.get() + /// } + /// ``` + pub TAIL_EXPR_DROP_ORDER, + Allow, + "Detect and warn on significant change in drop order in tail expression location", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), + reference: "issue #123739 ", + }; +} + declare_lint! { /// The `rust_2024_guarded_string_incompatible_syntax` lint detects `#` tokens /// that will be parsed as part of a guarded string literal in Rust 2024. diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 4e44de33611..114211b27c1 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -236,6 +236,11 @@ pub struct ScopeTree { /// during type check based on a traversal of the AST. pub rvalue_candidates: HirIdMap, + /// Backwards incompatible scoping that will be introduced in future editions. + /// This information is used later for linting to identify locals and + /// temporary values that will receive backwards-incompatible drop orders. + pub backwards_incompatible_scope: UnordMap, + /// If there are any `yield` nested within a scope, this map /// stores the `Span` of the last one and its index in the /// postorder of the Visitor traversal on the HIR. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index f0e2b7a376c..2bfcd0a6227 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -834,6 +834,11 @@ impl Debug for Statement<'_> { Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), ConstEvalCounter => write!(fmt, "ConstEvalCounter"), Nop => write!(fmt, "nop"), + BackwardIncompatibleDropHint { ref place, reason: _ } => { + // For now, we don't record the reason because there is only one use case, + // which is to report breaking change in drop order by Edition 2024 + write!(fmt, "backward incompatible drop({place:?})") + } } } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 2083279e128..fea940ea47c 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -432,6 +432,18 @@ pub enum StatementKind<'tcx> { /// No-op. Useful for deleting instructions without affecting statement indices. Nop, + + /// Marker statement indicating where `place` would be dropped. + /// This is semantically equivalent to `Nop`, so codegen and MIRI should interpret this + /// statement as such. + /// The only use case of this statement is for linting in MIR to detect temporary lifetime + /// changes. + BackwardIncompatibleDropHint { + /// Place to drop + place: Box>, + /// Reason for backward incompatibility + reason: BackwardIncompatibleDropReason, + }, } impl StatementKind<'_> { @@ -452,6 +464,7 @@ impl StatementKind<'_> { StatementKind::Intrinsic(..) => "Intrinsic", StatementKind::ConstEvalCounter => "ConstEvalCounter", StatementKind::Nop => "Nop", + StatementKind::BackwardIncompatibleDropHint { .. } => "BackwardIncompatibleDropHint", } } } @@ -897,6 +910,21 @@ pub enum TerminatorKind<'tcx> { }, } +#[derive( + Clone, + Debug, + TyEncodable, + TyDecodable, + Hash, + HashStable, + PartialEq, + TypeFoldable, + TypeVisitable +)] +pub enum BackwardIncompatibleDropReason { + Edition2024, +} + impl TerminatorKind<'_> { /// Returns a simple string representation of a `TerminatorKind` variant, independent of any /// values it might hold (e.g. `TerminatorKind::Call` always returns `"Call"`). diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 9f9ee8497b6..62c340d99e3 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -452,6 +452,7 @@ macro_rules! make_mir_visitor { } StatementKind::ConstEvalCounter => {} StatementKind::Nop => {} + StatementKind::BackwardIncompatibleDropHint { .. } => {} } } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 8fd99303622..970dc72e1ff 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -360,6 +360,14 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) { } } +impl<'tcx> Key for ty::ParamEnvAnd<'tcx, Ty<'tcx>> { + type Cache = DefaultCache; + + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for ty::TraitRef<'tcx> { type Cache = DefaultCache; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9ae519dfe7e..3fdb38a433e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1448,6 +1448,28 @@ rustc_queries! { cache_on_disk_if { false } } + /// Returns a list of types which (a) have a potentially significant destructor + /// and (b) may be dropped as a result of dropping a value of some type `ty` + /// (in the given environment). + /// + /// The idea of "significant" drop is somewhat informal and is used only for + /// diagnostics and edition migrations. The idea is that a significant drop may have + /// some visible side-effect on execution; freeing memory is NOT considered a side-effect. + /// The rules are as follows: + /// * Type with no explicit drop impl do not have significant drop. + /// * Types with a drop impl are assumed to have significant drop unless they have a `#[rustc_insignificant_dtor]` annotation. + /// + /// Note that insignificant drop is a "shallow" property. A type like `Vec` does not + /// have significant drop but the type `LockGuard` does, and so if `ty = Vec` + /// then the return value would be `&[LockGuard]`. + /// *IMPORTANT*: *DO NOT* run this query before promoted MIR body is constructed, + /// because this query partially depends on that query. + /// Otherwise, there is a risk of query cycles. + query list_significant_drop_tys(ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> &'tcx ty::List> { + desc { |tcx| "computing when `{}` has a significant destructor", ty.value } + cache_on_disk_if { false } + } + /// Computes the layout of a type. Note that this implicitly /// executes in "reveal all" mode, and will normalize the input type. query layout_of( diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 8f26e05cb72..06336d57704 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -247,13 +247,24 @@ pub struct Expr<'tcx> { pub ty: Ty<'tcx>, /// The lifetime of this expression if it should be spilled into a - /// temporary; should be `None` only if in a constant context - pub temp_lifetime: Option, + /// temporary + pub temp_lifetime: TempLifetime, /// span of the expression in the source pub span: Span, } +/// Temporary lifetime information for THIR expressions +#[derive(Clone, Copy, Debug, HashStable)] +pub struct TempLifetime { + /// Lifetime for temporaries as expected. + /// This should be `None` in a constant context. + pub temp_lifetime: Option, + /// If `Some(lt)`, indicates that the lifetime of this temporary will change to `lt` in a future edition. + /// If `None`, then no changes are expected, or lints are disabled. + pub backwards_incompatible: Option, +} + #[derive(Clone, Debug, HashStable)] pub enum ExprKind<'tcx> { /// `Scope`s are used to explicitly mark destruction scopes, @@ -1087,7 +1098,7 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(Block, 48); - static_assert_size!(Expr<'_>, 64); + static_assert_size!(Expr<'_>, 72); static_assert_size!(ExprKind<'_>, 40); static_assert_size!(Pat<'_>, 64); static_assert_size!(PatKind<'_>, 48); diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index 37dcf7c0d64..57c2d7623d2 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -18,15 +18,17 @@ impl RvalueScopes { } /// Returns the scope when the temp created by `expr_id` will be cleaned up. + /// It also emits a lint on potential backwards incompatible change to the temporary scope + /// which is *for now* always shortening. pub fn temporary_scope( &self, region_scope_tree: &ScopeTree, expr_id: hir::ItemLocalId, - ) -> Option { + ) -> (Option, Option) { // Check for a designated rvalue scope. if let Some(&s) = self.map.get(&expr_id) { debug!("temporary_scope({expr_id:?}) = {s:?} [custom]"); - return s; + return (s, None); } // Otherwise, locate the innermost terminating scope @@ -34,27 +36,40 @@ impl RvalueScopes { // have an enclosing scope, hence no scope will be // returned. let mut id = Scope { id: expr_id, data: ScopeData::Node }; + let mut backwards_incompatible = None; while let Some(&(p, _)) = region_scope_tree.parent_map.get(&id) { match p.data { ScopeData::Destruction => { debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]"); - return Some(id); + return (Some(id), backwards_incompatible); } ScopeData::IfThenRescope => { debug!("temporary_scope({expr_id:?}) = {p:?} [enclosing]"); - return Some(p); + return (Some(p), backwards_incompatible); } ScopeData::Node | ScopeData::CallSite | ScopeData::Arguments | ScopeData::IfThen - | ScopeData::Remainder(_) => id = p, + | ScopeData::Remainder(_) => { + // If we haven't already passed through a backwards-incompatible node, + // then check if we are passing through one now and record it if so. + // This is for now only working for cases where a temporary lifetime is + // *shortened*. + if backwards_incompatible.is_none() { + backwards_incompatible = region_scope_tree + .backwards_incompatible_scope + .get(&p.item_local_id()) + .copied(); + } + id = p + } } } debug!("temporary_scope({expr_id:?}) = None"); - None + (None, backwards_incompatible) } /// Make an association between a sub-expression and an extended lifetime diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 159959d4f1f..0cab853196b 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -1,6 +1,5 @@ //! See docs in build/expr/mod.rs -use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::*; use tracing::{debug, instrument}; @@ -9,6 +8,12 @@ use crate::build::expr::category::Category; use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary}; impl<'a, 'tcx> Builder<'a, 'tcx> { + /// Construct a temporary lifetime restricted to just the local scope + pub(crate) fn local_temp_lifetime(&self) -> TempLifetime { + let local_scope = self.local_scope(); + TempLifetime { temp_lifetime: Some(local_scope), backwards_incompatible: None } + } + /// Returns an operand suitable for use until the end of the current /// scope expression. /// @@ -21,8 +26,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block: BasicBlock, expr_id: ExprId, ) -> BlockAnd> { - let local_scope = self.local_scope(); - self.as_operand(block, Some(local_scope), expr_id, LocalInfo::Boring, NeedsTemporary::Maybe) + self.as_operand( + block, + self.local_temp_lifetime(), + expr_id, + LocalInfo::Boring, + NeedsTemporary::Maybe, + ) } /// Returns an operand suitable for use until the end of the current scope expression and @@ -80,8 +90,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block: BasicBlock, expr: ExprId, ) -> BlockAnd> { - let local_scope = self.local_scope(); - self.as_call_operand(block, Some(local_scope), expr) + self.as_call_operand(block, self.local_temp_lifetime(), expr) } /// Compile `expr` into a value that can be used as an operand. @@ -102,7 +111,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn as_operand( &mut self, mut block: BasicBlock, - scope: Option, + scope: TempLifetime, expr_id: ExprId, local_info: LocalInfo<'tcx>, needs_temporary: NeedsTemporary, @@ -146,7 +155,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn as_call_operand( &mut self, mut block: BasicBlock, - scope: Option, + scope: TempLifetime, expr_id: ExprId, ) -> BlockAnd> { let this = self; diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 9f6e0735b48..6ce88cdc39d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -6,7 +6,6 @@ use std::iter; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_hir::def_id::LocalDefId; use rustc_middle::hir::place::{Projection as HirProjection, ProjectionKind as HirProjectionKind}; -use rustc_middle::middle::region; use rustc_middle::mir::AssertKind::BoundsCheck; use rustc_middle::mir::*; use rustc_middle::thir::*; @@ -598,7 +597,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { index: ExprId, mutability: Mutability, fake_borrow_temps: Option<&mut Vec>, - temp_lifetime: Option, + temp_lifetime: TempLifetime, expr_span: Span, source_info: SourceInfo, ) -> BlockAnd> { diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index a3fee38908b..3f89e337781 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -33,14 +33,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_id: ExprId, ) -> BlockAnd> { let local_scope = self.local_scope(); - self.as_rvalue(block, Some(local_scope), expr_id) + self.as_rvalue( + block, + TempLifetime { temp_lifetime: Some(local_scope), backwards_incompatible: None }, + expr_id, + ) } /// Compile `expr`, yielding an rvalue. pub(crate) fn as_rvalue( &mut self, mut block: BasicBlock, - scope: Option, + scope: TempLifetime, expr_id: ExprId, ) -> BlockAnd> { let this = self; @@ -171,7 +175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, kind: StatementKind::StorageLive(result), }); - if let Some(scope) = scope { + if let Some(scope) = scope.temp_lifetime { // schedule a shallow free of that memory, lest we unwind: this.schedule_drop_storage_and_value(expr_span, scope, result); } @@ -445,7 +449,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block = this.limit_capture_mutability( upvar_expr.span, upvar_expr.ty, - scope, + scope.temp_lifetime, block, arg, ) @@ -705,7 +709,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, value: ExprId, - scope: Option, + scope: TempLifetime, outer_source_info: SourceInfo, ) -> BlockAnd> { let this = self; diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index b8b5e4634ed..466f67b1ba4 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -2,7 +2,6 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::HirId; -use rustc_middle::middle::region; use rustc_middle::middle::region::{Scope, ScopeData}; use rustc_middle::mir::*; use rustc_middle::thir::*; @@ -17,7 +16,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn as_temp( &mut self, block: BasicBlock, - temp_lifetime: Option, + temp_lifetime: TempLifetime, expr_id: ExprId, mutability: Mutability, ) -> BlockAnd { @@ -31,7 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn as_temp_inner( &mut self, mut block: BasicBlock, - temp_lifetime: Option, + temp_lifetime: TempLifetime, expr_id: ExprId, mutability: Mutability, ) -> BlockAnd { @@ -47,8 +46,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let expr_ty = expr.ty; - let deduplicate_temps = - this.fixed_temps_scope.is_some() && this.fixed_temps_scope == temp_lifetime; + let deduplicate_temps = this.fixed_temps_scope.is_some() + && this.fixed_temps_scope == temp_lifetime.temp_lifetime; let temp = if deduplicate_temps && let Some(temp_index) = this.fixed_temps.get(&expr_id) { *temp_index } else { @@ -76,7 +75,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { LocalInfo::BlockTailTemp(tail_info) } - _ if let Some(Scope { data: ScopeData::IfThenRescope, id }) = temp_lifetime => { + _ if let Some(Scope { data: ScopeData::IfThenRescope, id }) = + temp_lifetime.temp_lifetime => + { LocalInfo::IfThenRescopeTemp { if_then: HirId { owner: this.hir_id.owner, local_id: id }, } @@ -117,7 +118,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Anything with a shorter lifetime (e.g the `&foo()` in // `bar(&foo())` or anything within a block will keep the // regular drops just like runtime code. - if let Some(temp_lifetime) = temp_lifetime { + if let Some(temp_lifetime) = temp_lifetime.temp_lifetime { this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Storage); } } @@ -125,10 +126,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block = this.expr_into_dest(temp_place, block, expr_id).into_block(); - if let Some(temp_lifetime) = temp_lifetime { + if let Some(temp_lifetime) = temp_lifetime.temp_lifetime { this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value); } + if let Some(backwards_incompatible) = temp_lifetime.backwards_incompatible { + this.schedule_backwards_incompatible_drop(expr_span, backwards_incompatible, temp); + } + block.and(temp) } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 0dec56d21ae..bebb44faba6 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -139,7 +139,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // (#66975) Source could be a const of type `!`, so has to // exist in the generated MIR. unpack!( - block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut) + block = + this.as_temp(block, this.local_temp_lifetime(), source, Mutability::Mut) ); // This is an optimization. If the expression was a call then we already have an @@ -321,7 +322,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let is_union = adt_def.is_union(); let active_field_index = is_union.then(|| fields[0].name); - let scope = this.local_scope(); + let scope = this.local_temp_lifetime(); // first process the set of fields that were provided // (evaluating them in order given by user) @@ -333,7 +334,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { unpack!( block = this.as_operand( block, - Some(scope), + scope, f.expr, LocalInfo::AggregateTemp, NeedsTemporary::Maybe, @@ -548,15 +549,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Yield { value } => { - let scope = this.local_scope(); + let scope = this.local_temp_lifetime(); let value = unpack!( - block = this.as_operand( - block, - Some(scope), - value, - LocalInfo::Boring, - NeedsTemporary::No - ) + block = + this.as_operand(block, scope, value, LocalInfo::Boring, NeedsTemporary::No) ); let resume = this.cfg.start_new_block(); this.cfg.terminate(block, source_info, TerminatorKind::Yield { diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index 02ca12028d3..15ee6dd014c 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -172,8 +172,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None }; - let temp = - unpack!(block = this.as_temp(block, statement_scope, expr_id, Mutability::Not)); + let temp = unpack!( + block = this.as_temp( + block, + TempLifetime { + temp_lifetime: statement_scope, + backwards_incompatible: None + }, + expr_id, + Mutability::Not + ) + ); if let Some(span) = adjusted_span { this.local_decls[temp].source_info.span = span; diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index a62d4e9d873..a4d16295880 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -202,8 +202,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Increment the decision depth, in case we encounter boolean expressions // further down. this.mcdc_increment_depth_if_enabled(); - let place = - unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability)); + let place = unpack!( + block = this.as_temp( + block, + TempLifetime { + temp_lifetime: Some(temp_scope), + backwards_incompatible: None + }, + expr_id, + mutability + ) + ); this.mcdc_decrement_depth_if_enabled(); let operand = Operand::Move(Place::from(place)); diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index e63fbeeac66..636e47b7ad2 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -89,7 +89,7 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::{ExprId, LintLevel}; -use rustc_middle::{bug, span_bug}; +use rustc_middle::{bug, span_bug, ty}; use rustc_session::lint::Level; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span}; @@ -151,6 +151,9 @@ struct DropData { /// Whether this is a value Drop or a StorageDead. kind: DropKind, + + /// Whether this is a backwards-incompatible drop lint + backwards_incompatible_lint: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -274,8 +277,12 @@ impl DropTree { // represents the block in the tree that should be jumped to once all // of the required drops have been performed. let fake_source_info = SourceInfo::outermost(DUMMY_SP); - let fake_data = - DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage }; + let fake_data = DropData { + source_info: fake_source_info, + local: Local::MAX, + kind: DropKind::Storage, + backwards_incompatible_lint: false, + }; let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]); Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() } } @@ -763,7 +770,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local = place.as_local().unwrap_or_else(|| bug!("projection in tail call args")); - Some(DropData { source_info, local, kind: DropKind::Value }) + Some(DropData { + source_info, + local, + kind: DropKind::Value, + backwards_incompatible_lint: false, + }) } Operand::Constant(_) => None, }) @@ -1019,9 +1031,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if local.index() <= self.arg_count { span_bug!( span, - "`schedule_drop` called with local {:?} and arg_count {}", + "`schedule_drop` called with body argument {:?} \ + but its storage does not require a drop", local, - self.arg_count, ) } false @@ -1089,6 +1101,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info: SourceInfo { span: scope_end, scope: scope.source_scope }, local, kind: drop_kind, + backwards_incompatible_lint: false, }); return; @@ -1098,6 +1111,45 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, local); } + /// Schedule emission of a backwards incompatible drop lint hint. + /// Applicable only to temporary values for now. + pub(crate) fn schedule_backwards_incompatible_drop( + &mut self, + span: Span, + region_scope: region::Scope, + local: Local, + ) { + if !self.local_decls[local].ty.has_significant_drop(self.tcx, ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env: self.param_env, + }) { + return; + } + for scope in self.scopes.scopes.iter_mut().rev() { + // Since we are inserting linting MIR statement, we have to invalidate the caches + scope.invalidate_cache(); + if scope.region_scope == region_scope { + let region_scope_span = region_scope.span(self.tcx, self.region_scope_tree); + let scope_end = self.tcx.sess.source_map().end_point(region_scope_span); + + scope.drops.push(DropData { + source_info: SourceInfo { span: scope_end, scope: scope.source_scope }, + local, + kind: DropKind::Value, + backwards_incompatible_lint: true, + }); + + return; + } + } + span_bug!( + span, + "region scope {:?} not in scope to drop {:?} for linting", + region_scope, + local + ); + } + /// Indicates that the "local operand" stored in `local` is /// *moved* at some point during execution (see `local_scope` for /// more information about what a "local operand" is -- in short, @@ -1378,16 +1430,25 @@ fn build_scope_drops<'tcx>( continue; } - unwind_drops.add_entry_point(block, unwind_to); - - let next = cfg.start_new_block(); - cfg.terminate(block, source_info, TerminatorKind::Drop { - place: local.into(), - target: next, - unwind: UnwindAction::Continue, - replace: false, - }); - block = next; + if drop_data.backwards_incompatible_lint { + cfg.push(block, Statement { + source_info, + kind: StatementKind::BackwardIncompatibleDropHint { + place: Box::new(local.into()), + reason: BackwardIncompatibleDropReason::Edition2024, + }, + }); + } else { + unwind_drops.add_entry_point(block, unwind_to); + let next = cfg.start_new_block(); + cfg.terminate(block, source_info, TerminatorKind::Drop { + place: local.into(), + target: next, + unwind: UnwindAction::Continue, + replace: false, + }); + block = next; + } } DropKind::Storage => { if storage_dead_on_unwind { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 198fa4ffb7a..47b7f332951 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -23,7 +23,6 @@ use tracing::{debug, info, instrument, trace}; use crate::errors; use crate::thir::cx::Cx; -use crate::thir::cx::region::Scope; use crate::thir::util::UserAnnotatedTyHelpers; impl<'tcx> Cx<'tcx> { @@ -240,7 +239,7 @@ impl<'tcx> Cx<'tcx> { fn mirror_expr_cast( &mut self, source: &'tcx hir::Expr<'tcx>, - temp_lifetime: Option, + temp_lifetime: TempLifetime, span: Span, ) -> ExprKind<'tcx> { let tcx = self.tcx; @@ -325,7 +324,7 @@ impl<'tcx> Cx<'tcx> { fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { let tcx = self.tcx; let expr_ty = self.typeck_results().expr_ty(expr); - let temp_lifetime = + let (temp_lifetime, backwards_incompatible) = self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id); let kind = match expr.kind { @@ -361,7 +360,7 @@ impl<'tcx> Cx<'tcx> { let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e)); let tupled_args = Expr { ty: Ty::new_tup_from_iter(tcx, arg_tys), - temp_lifetime, + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, span: expr.span, kind: ExprKind::Tuple { fields: self.mirror_exprs(args) }, }; @@ -391,7 +390,10 @@ impl<'tcx> Cx<'tcx> { && let [value] = args { return Expr { - temp_lifetime, + temp_lifetime: TempLifetime { + temp_lifetime, + backwards_incompatible, + }, ty: expr_ty, span: expr.span, kind: ExprKind::Box { value: self.mirror_expr(value) }, @@ -811,13 +813,13 @@ impl<'tcx> Cx<'tcx> { }, hir::ExprKind::Loop(body, ..) => { let block_ty = self.typeck_results().node_type(body.hir_id); - let temp_lifetime = self + let (temp_lifetime, backwards_incompatible) = self .rvalue_scopes .temporary_scope(self.region_scope_tree, body.hir_id.local_id); let block = self.mirror_block(body); let body = self.thir.exprs.push(Expr { ty: block_ty, - temp_lifetime, + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, span: self.thir[block].span, kind: ExprKind::Block { block }, }); @@ -838,13 +840,17 @@ impl<'tcx> Cx<'tcx> { expr, cast_ty.hir_id, user_ty, ); - let cast = self.mirror_expr_cast(source, temp_lifetime, expr.span); + let cast = self.mirror_expr_cast( + source, + TempLifetime { temp_lifetime, backwards_incompatible }, + expr.span, + ); if let Some(user_ty) = user_ty { // NOTE: Creating a new Expr and wrapping a Cast inside of it may be // inefficient, revisit this when performance becomes an issue. let cast_expr = self.thir.exprs.push(Expr { - temp_lifetime, + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, ty: expr_ty, span: expr.span, kind: cast, @@ -887,7 +893,12 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Err(_) => unreachable!("cannot lower a `hir::ExprKind::Err` to THIR"), }; - Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind } + Expr { + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, + ty: expr_ty, + span: expr.span, + kind, + } } fn user_args_applied_to_res( @@ -931,7 +942,7 @@ impl<'tcx> Cx<'tcx> { span: Span, overloaded_callee: Option>, ) -> Expr<'tcx> { - let temp_lifetime = + let (temp_lifetime, backwards_incompatible) = self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id); let (ty, user_ty) = match overloaded_callee { Some(fn_def) => (fn_def, None), @@ -952,7 +963,12 @@ impl<'tcx> Cx<'tcx> { ) } }; - Expr { temp_lifetime, ty, span, kind: ExprKind::ZstLiteral { user_ty } } + Expr { + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, + ty, + span, + kind: ExprKind::ZstLiteral { user_ty }, + } } fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId { @@ -1025,7 +1041,7 @@ impl<'tcx> Cx<'tcx> { Res::Def(DefKind::Static { .. }, id) => { // this is &raw for extern static or static mut, and & for other statics let ty = self.tcx.static_ptr_ty(id, self.typing_env()); - let temp_lifetime = self + let (temp_lifetime, backwards_incompatible) = self .rvalue_scopes .temporary_scope(self.region_scope_tree, expr.hir_id.local_id); let kind = if self.tcx.is_thread_local_static(id) { @@ -1035,7 +1051,12 @@ impl<'tcx> Cx<'tcx> { ExprKind::StaticRef { alloc_id, ty, def_id: id } }; ExprKind::Deref { - arg: self.thir.exprs.push(Expr { ty, temp_lifetime, span: expr.span, kind }), + arg: self.thir.exprs.push(Expr { + ty, + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, + span: expr.span, + kind, + }), } } @@ -1106,13 +1127,13 @@ impl<'tcx> Cx<'tcx> { // construct the complete expression `foo()` for the overloaded call, // which will yield the &T type - let temp_lifetime = + let (temp_lifetime, backwards_incompatible) = self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id); let fun = self.method_callee(expr, span, overloaded_callee); let fun = self.thir.exprs.push(fun); let fun_ty = self.thir[fun].ty; let ref_expr = self.thir.exprs.push(Expr { - temp_lifetime, + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, ty: ref_ty, span, kind: ExprKind::Call { ty: fun_ty, fun, args, from_hir_call: false, fn_span: span }, @@ -1127,7 +1148,7 @@ impl<'tcx> Cx<'tcx> { closure_expr: &'tcx hir::Expr<'tcx>, place: HirPlace<'tcx>, ) -> Expr<'tcx> { - let temp_lifetime = self + let (temp_lifetime, backwards_incompatible) = self .rvalue_scopes .temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id); let var_ty = place.base_ty; @@ -1143,7 +1164,7 @@ impl<'tcx> Cx<'tcx> { }; let mut captured_place_expr = Expr { - temp_lifetime, + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, ty: var_ty, span: closure_expr.span, kind: self.convert_var(var_hir_id), @@ -1168,8 +1189,12 @@ impl<'tcx> Cx<'tcx> { } }; - captured_place_expr = - Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind }; + captured_place_expr = Expr { + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, + ty: proj.ty, + span: closure_expr.span, + kind, + }; } captured_place_expr @@ -1184,7 +1209,7 @@ impl<'tcx> Cx<'tcx> { let upvar_capture = captured_place.info.capture_kind; let captured_place_expr = self.convert_captured_hir_place(closure_expr, captured_place.place.clone()); - let temp_lifetime = self + let (temp_lifetime, backwards_incompatible) = self .rvalue_scopes .temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id); @@ -1201,7 +1226,7 @@ impl<'tcx> Cx<'tcx> { } }; Expr { - temp_lifetime, + temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, ty: upvar_ty, span: closure_expr.span, kind: ExprKind::Borrow { diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index e06c1f2bb49..fd7254a0210 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -253,6 +253,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => None, }; if let Some(destination) = destination { diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index c5fd2a631ff..576289e228a 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -157,6 +157,7 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { | StatementKind::Nop | StatementKind::Retag(..) | StatementKind::Intrinsic(..) + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::StorageLive(..) => {} } } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index fd8e403ebc2..0880364bfca 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -385,6 +385,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => {} } } diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index 9bbfae17fd9..d00bfc66a6a 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -25,6 +25,31 @@ mir_transform_must_not_suspend = {$pre}`{$def_path}`{$post} held across a suspen .help = consider using a block (`{"{ ... }"}`) to shrink the value's scope, ending before the suspend point mir_transform_operation_will_panic = this operation will panic at runtime +mir_transform_tail_expr_drop_order = relative drop order changing in Rust 2024 + .temporaries = in Rust 2024, this temporary value will be dropped first + .observers = in Rust 2024, this local variable or temporary value will be dropped second + .note_dtors = + dropping the temporary value runs this custom `Drop` impl, which we could not prove to be side-effect free + .note_observer_dtors = + dropping the local runs this custom `Drop` impl, which we could not prove to be side-effect free + .drop_location = + now the temporary value is dropped here, before the local variables in the block or statement + .note_epilogue = most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + .label_local_epilogue = {$is_dropped_first_edition_2024 -> + [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 + *[false] `{$name}` will be dropped later as of Edition 2024 + } + +mir_transform_tail_expr_dtor = {$dtor_kind -> + [dyn] `{$name}` may invoke a custom destructor because it contains a trait object + *[concrete] `{$name}` invokes this custom destructor + } + +mir_transform_tail_expr_local = {$is_generated_name -> + [true] this value will be stored in a temporary; let us call it `{$name}` + *[false] `{$name}` calls a custom destructor + } + mir_transform_unaligned_packed_ref = reference to packed field is unaligned .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index d38a1dd11dc..8295a806d71 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1772,6 +1772,7 @@ impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> { | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => {} } } diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 875db23ce09..824d657e1fc 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -97,6 +97,7 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option { StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::ConstEvalCounter + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => None, // FIXME(#78546): MIR InstrumentCoverage - Can the source_info.span for `FakeRead` diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 26480be29f3..d017202f48b 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -186,7 +186,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { | StatementKind::FakeRead(..) | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) - | StatementKind::AscribeUserType(..) => (), + | StatementKind::BackwardIncompatibleDropHint { .. } + | StatementKind::AscribeUserType(..) => {} } } diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 2898f82e25c..0c75cdadc92 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -99,7 +99,8 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { | StatementKind::Intrinsic(_) | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(_) - | StatementKind::Nop => (), + | StatementKind::BackwardIncompatibleDropHint { .. } + | StatementKind::Nop => {} StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => { bug!("{:?} not found in this MIR phase!", statement.kind) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index beeab0d4a66..9c74b2f0839 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -581,7 +581,7 @@ impl WriteInfo { | Rvalue::RawPtr(_, _) | Rvalue::Len(_) | Rvalue::Discriminant(_) - | Rvalue::CopyForDeref(_) => (), + | Rvalue::CopyForDeref(_) => {} } } // Retags are technically also reads, but reporting them as a write suffices @@ -596,7 +596,8 @@ impl WriteInfo { | StatementKind::Coverage(_) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) - | StatementKind::PlaceMention(_) => (), + | StatementKind::BackwardIncompatibleDropHint { .. } + | StatementKind::PlaceMention(_) => {} StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => { bug!("{:?} not found in this MIR phase", statement) } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 5c2c36db0f7..beed007589b 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -352,6 +352,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { | StatementKind::FakeRead(..) | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => None, } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 5651bf469d5..bfb842e4485 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -50,6 +50,7 @@ mod deduce_param_attrs; mod errors; mod ffi_unwind_calls; mod lint; +mod lint_tail_expr_drop_order; mod shim; mod ssa; @@ -490,6 +491,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & } let (body, _) = tcx.mir_promoted(def); + lint_tail_expr_drop_order::run_lint(tcx, def, &body.borrow()); let mut body = body.steal(); if let Some(error_reported) = tainted_by_errors { diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs new file mode 100644 index 00000000000..b8502fcbafb --- /dev/null +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -0,0 +1,701 @@ +use std::cell::RefCell; +use std::collections::hash_map; +use std::rc::Rc; + +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::unord::{UnordMap, UnordSet}; +use rustc_errors::Subdiagnostic; +use rustc_hir::CRATE_HIR_ID; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_index::bit_set::ChunkedBitSet; +use rustc_index::{IndexSlice, IndexVec}; +use rustc_macros::{LintDiagnostic, Subdiagnostic}; +use rustc_middle::bug; +use rustc_middle::mir::{ + self, BasicBlock, Body, ClearCrossCrate, Local, Location, Place, StatementKind, TerminatorKind, + dump_mir, +}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_mir_dataflow::impls::MaybeInitializedPlaces; +use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; +use rustc_mir_dataflow::{Analysis, MaybeReachable, ResultsCursor}; +use rustc_session::lint::builtin::TAIL_EXPR_DROP_ORDER; +use rustc_session::lint::{self}; +use rustc_span::{DUMMY_SP, Span, Symbol}; +use rustc_type_ir::data_structures::IndexMap; +use smallvec::{SmallVec, smallvec}; +use tracing::{debug, instrument}; + +fn place_has_common_prefix<'tcx>(left: &Place<'tcx>, right: &Place<'tcx>) -> bool { + left.local == right.local + && left.projection.iter().zip(right.projection).all(|(left, right)| left == right) +} + +/// Cache entry of `drop` at a `BasicBlock` +#[derive(Debug, Clone, Copy)] +enum MovePathIndexAtBlock { + /// We know nothing yet + Unknown, + /// We know that the `drop` here has no effect + None, + /// We know that the `drop` here will invoke a destructor + Some(MovePathIndex), +} + +struct DropsReachable<'a, 'mir, 'tcx> { + body: &'a Body<'tcx>, + place: &'a Place<'tcx>, + drop_span: &'a mut Option, + move_data: &'a MoveData<'tcx>, + maybe_init: &'a mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, + block_drop_value_info: &'a mut IndexSlice, + collected_drops: &'a mut ChunkedBitSet, + visited: FxHashMap>>>, +} + +impl<'a, 'mir, 'tcx> DropsReachable<'a, 'mir, 'tcx> { + fn visit(&mut self, block: BasicBlock) { + let move_set_size = self.move_data.move_paths.len(); + let make_new_path_set = || Rc::new(RefCell::new(ChunkedBitSet::new_empty(move_set_size))); + + let data = &self.body.basic_blocks[block]; + let Some(terminator) = &data.terminator else { return }; + // Given that we observe these dropped locals here at `block` so far, + // we will try to update the successor blocks. + // An occupied entry at `block` in `self.visited` signals that we have visited `block` before. + let dropped_local_here = + Rc::clone(self.visited.entry(block).or_insert_with(make_new_path_set)); + // We could have invoked reverse lookup for a `MovePathIndex` every time, but unfortunately it is expensive. + // Let's cache them in `self.block_drop_value_info`. + match self.block_drop_value_info[block] { + MovePathIndexAtBlock::Some(dropped) => { + dropped_local_here.borrow_mut().insert(dropped); + } + MovePathIndexAtBlock::Unknown => { + if let TerminatorKind::Drop { place, .. } = &terminator.kind + && let LookupResult::Exact(idx) | LookupResult::Parent(Some(idx)) = + self.move_data.rev_lookup.find(place.as_ref()) + { + // Since we are working with MIRs at a very early stage, + // observing a `drop` terminator is not indicative enough that + // the drop will definitely happen. + // That is decided in the drop elaboration pass instead. + // Therefore, we need to consult with the maybe-initialization information. + self.maybe_init.seek_before_primary_effect(Location { + block, + statement_index: data.statements.len(), + }); + + // Check if the drop of `place` under inspection is really in effect. + // This is true only when `place` may have been initialized along a control flow path from a BID to the drop program point today. + // In other words, this is where the drop of `place` will happen in the future instead. + if let MaybeReachable::Reachable(maybe_init) = self.maybe_init.get() + && maybe_init.contains(idx) + { + // We also cache the drop information, so that we do not need to check on data-flow cursor again + self.block_drop_value_info[block] = MovePathIndexAtBlock::Some(idx); + dropped_local_here.borrow_mut().insert(idx); + } else { + self.block_drop_value_info[block] = MovePathIndexAtBlock::None; + } + } + } + MovePathIndexAtBlock::None => {} + } + + for succ in terminator.successors() { + let target = &self.body.basic_blocks[succ]; + if target.is_cleanup { + continue; + } + + // As long as we are passing through a new block, or new dropped places to propagate, + // we will proceed with `succ` + let dropped_local_there = match self.visited.entry(succ) { + hash_map::Entry::Occupied(occupied_entry) => { + if succ == block + || !occupied_entry.get().borrow_mut().union(&*dropped_local_here.borrow()) + { + // `succ` has been visited but no new drops observed so far, + // so we can bail on `succ` until new drop information arrives + continue; + } + Rc::clone(occupied_entry.get()) + } + hash_map::Entry::Vacant(vacant_entry) => Rc::clone( + vacant_entry.insert(Rc::new(RefCell::new(dropped_local_here.borrow().clone()))), + ), + }; + if let Some(terminator) = &target.terminator + && let TerminatorKind::Drop { + place: dropped_place, + target: _, + unwind: _, + replace: _, + } = &terminator.kind + && place_has_common_prefix(dropped_place, self.place) + { + // We have now reached the current drop of the `place`. + // Let's check the observed dropped places in. + self.collected_drops.union(&*dropped_local_there.borrow()); + if self.drop_span.is_none() { + // FIXME(@dingxiangfei2009): it turns out that `self.body.source_scopes` are still a bit wonky. + // There is a high chance that this span still points to a block rather than a statement semicolon. + *self.drop_span = Some(terminator.source_info.span); + } + // Now we have discovered a simple control flow path from a future drop point + // to the current drop point. + // We will not continue from there. + } else { + self.visit(succ) + } + } + } +} + +/// An additional filter to exclude well-known types from the ecosystem +/// because their drops are trivial. +/// This returns additional types to check if the drops are delegated to those. +/// A typical example is `hashbrown::HashMap`, whose drop is delegated to `K` and `V`. +fn true_significant_drop_ty<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, +) -> Option; 2]>> { + if let ty::Adt(def, args) = ty.kind() { + let mut did = def.did(); + let mut name_rev = vec![]; + loop { + let key = tcx.def_key(did); + + match key.disambiguated_data.data { + rustc_hir::definitions::DefPathData::CrateRoot => { + name_rev.push(tcx.crate_name(did.krate)) + } + rustc_hir::definitions::DefPathData::TypeNs(symbol) => name_rev.push(symbol), + _ => return None, + } + if let Some(parent) = key.parent { + did = DefId { krate: did.krate, index: parent }; + } else { + break; + } + } + let name_str: Vec<_> = name_rev.iter().rev().map(|x| x.as_str()).collect(); + debug!(?name_str); + match name_str[..] { + // These are the types from Rust core ecosystem + ["sym" | "proc_macro2", ..] + | ["core" | "std", "task", "LocalWaker" | "Waker"] + | ["core" | "std", "task", "wake", "LocalWaker" | "Waker"] => Some(smallvec![]), + // These are important types from Rust ecosystem + ["tracing", "instrument", "Instrumented"] | ["bytes", "Bytes"] => Some(smallvec![]), + ["hashbrown", "raw", "RawTable" | "RawIntoIter"] => { + if let [ty, ..] = &***args + && let Some(ty) = ty.as_type() + { + Some(smallvec![ty]) + } else { + None + } + } + ["hashbrown", "raw", "RawDrain"] => { + if let [_, ty, ..] = &***args + && let Some(ty) = ty.as_type() + { + Some(smallvec![ty]) + } else { + None + } + } + _ => None, + } + } else { + None + } +} + +/// Returns the list of types with a "potentially sigificant" that may be dropped +/// by dropping a value of type `ty`. +#[instrument(level = "debug", skip(tcx, param_env))] +fn extract_component_raw<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + ty_seen: &mut UnordSet>, +) -> SmallVec<[Ty<'tcx>; 4]> { + // Droppiness does not depend on regions, so let us erase them. + let ty = tcx + .try_normalize_erasing_regions( + ty::TypingEnv { param_env, typing_mode: ty::TypingMode::PostAnalysis }, + ty, + ) + .unwrap_or(ty); + + let tys = tcx.list_significant_drop_tys(param_env.and(ty)); + debug!(?ty, "components"); + let mut out_tys = smallvec![]; + for ty in tys { + if let Some(tys) = true_significant_drop_ty(tcx, ty) { + // Some types can be further opened up because the drop is simply delegated + for ty in tys { + if ty_seen.insert(ty) { + out_tys.extend(extract_component_raw(tcx, param_env, ty, ty_seen)); + } + } + } else { + if ty_seen.insert(ty) { + out_tys.push(ty); + } + } + } + out_tys +} + +#[instrument(level = "debug", skip(tcx, param_env))] +fn extract_component_with_significant_dtor<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, +) -> SmallVec<[Ty<'tcx>; 4]> { + let mut tys = extract_component_raw(tcx, param_env, ty, &mut Default::default()); + let mut deduplicate = FxHashSet::default(); + tys.retain(|oty| deduplicate.insert(*oty)); + tys.into_iter().collect() +} + +/// Extract the span of the custom destructor of a type +/// especially the span of the `impl Drop` header or its entire block +/// when we are working with current local crate. +#[instrument(level = "debug", skip(tcx))] +fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { + match ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Error(_) + | ty::Str + | ty::Never + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnPtr(_, _) + | ty::Tuple(_) + | ty::Dynamic(_, _, _) + | ty::Alias(_, _) + | ty::Bound(_, _) + | ty::Pat(_, _) + | ty::Placeholder(_) + | ty::Infer(_) + | ty::Slice(_) + | ty::Array(_, _) => None, + ty::Adt(adt_def, _) => { + let did = adt_def.did(); + let try_local_did_span = |did: DefId| { + if let Some(local) = did.as_local() { + tcx.source_span(local) + } else { + tcx.def_span(did) + } + }; + let dtor = if let Some(dtor) = tcx.adt_destructor(did) { + dtor.did + } else if let Some(dtor) = tcx.adt_async_destructor(did) { + dtor.future + } else { + return Some(try_local_did_span(did)); + }; + let def_key = tcx.def_key(dtor); + let Some(parent_index) = def_key.parent else { return Some(try_local_did_span(dtor)) }; + let parent_did = DefId { index: parent_index, krate: dtor.krate }; + Some(try_local_did_span(parent_did)) + } + ty::Coroutine(did, _) + | ty::CoroutineWitness(did, _) + | ty::CoroutineClosure(did, _) + | ty::Closure(did, _) + | ty::FnDef(did, _) + | ty::Foreign(did) => Some(tcx.def_span(did)), + ty::Param(_) => None, + } +} + +/// Check if a moved place at `idx` is a part of a BID. +/// The use of this check is that we will consider drops on these +/// as a drop of the overall BID and, thus, we can exclude it from the diagnosis. +fn place_descendent_of_bids<'tcx>( + mut idx: MovePathIndex, + move_data: &MoveData<'tcx>, + bids: &UnordSet<&Place<'tcx>>, +) -> bool { + loop { + let path = &move_data.move_paths[idx]; + if bids.contains(&path.place) { + return true; + } + if let Some(parent) = path.parent { + idx = parent; + } else { + return false; + } + } +} + +/// The core of the lint `tail-expr-drop-order` +pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<'tcx>) { + if matches!(tcx.def_kind(def_id), rustc_hir::def::DefKind::SyntheticCoroutineBody) { + // A synthetic coroutine has no HIR body and it is enough to just analyse the original body + return; + } + if body.span.edition().at_least_rust_2024() + || tcx.lints_that_dont_need_to_run(()).contains(&lint::LintId::of(TAIL_EXPR_DROP_ORDER)) + { + return; + } + // ## About BIDs in blocks ## + // Track the set of blocks that contain a backwards-incompatible drop (BID) + // and, for each block, the vector of locations. + // + // We group them per-block because they tend to scheduled in the same drop ladder block. + let mut bid_per_block = IndexMap::default(); + let mut bid_places = UnordSet::new(); + let param_env = tcx.param_env(def_id).with_reveal_all_normalized(tcx); + let mut ty_dropped_components = UnordMap::default(); + for (block, data) in body.basic_blocks.iter_enumerated() { + for (statement_index, stmt) in data.statements.iter().enumerate() { + if let StatementKind::BackwardIncompatibleDropHint { place, reason: _ } = &stmt.kind { + let ty = place.ty(body, tcx).ty; + if ty_dropped_components + .entry(ty) + .or_insert_with(|| extract_component_with_significant_dtor(tcx, param_env, ty)) + .is_empty() + { + continue; + } + bid_per_block + .entry(block) + .or_insert(vec![]) + .push((Location { block, statement_index }, &**place)); + bid_places.insert(&**place); + } + } + } + if bid_per_block.is_empty() { + return; + } + + dump_mir(tcx, false, "lint_tail_expr_drop_order", &0 as _, body, |_, _| Ok(())); + let locals_with_user_names = collect_user_names(body); + let is_closure_like = tcx.is_closure_like(def_id.to_def_id()); + + // Compute the "maybe initialized" information for this body. + // When we encounter a DROP of some place P we only care + // about the drop if `P` may be initialized. + let move_data = MoveData::gather_moves(body, tcx, |_| true); + let maybe_init = MaybeInitializedPlaces::new(tcx, body, &move_data); + let mut maybe_init = maybe_init.iterate_to_fixpoint(tcx, body, None).into_results_cursor(body); + let mut block_drop_value_info = + IndexVec::from_elem_n(MovePathIndexAtBlock::Unknown, body.basic_blocks.len()); + for (&block, candidates) in &bid_per_block { + // We will collect drops on locals on paths between BID points to their actual drop locations + // into `all_locals_dropped`. + let mut all_locals_dropped = ChunkedBitSet::new_empty(move_data.move_paths.len()); + let mut drop_span = None; + for &(_, place) in candidates.iter() { + let mut collected_drops = ChunkedBitSet::new_empty(move_data.move_paths.len()); + // ## On detecting change in relative drop order ## + // Iterate through each BID-containing block `block`. + // If the place `P` targeted by the BID is "maybe initialized", + // then search forward to find the actual `DROP(P)` point. + // Everything dropped between the BID and the actual drop point + // is something whose relative drop order will change. + DropsReachable { + body, + place, + drop_span: &mut drop_span, + move_data: &move_data, + maybe_init: &mut maybe_init, + block_drop_value_info: &mut block_drop_value_info, + collected_drops: &mut collected_drops, + visited: Default::default(), + } + .visit(block); + // Compute the set `all_locals_dropped` of local variables that are dropped + // after the BID point but before the current drop point. + // + // These are the variables whose drop impls will be reordered with respect + // to `place`. + all_locals_dropped.union(&collected_drops); + } + + // We shall now exclude some local bindings for the following cases. + { + let mut to_exclude = ChunkedBitSet::new_empty(all_locals_dropped.domain_size()); + // We will now do subtraction from the candidate dropped locals, because of the following reasons. + for path_idx in all_locals_dropped.iter() { + let move_path = &move_data.move_paths[path_idx]; + let dropped_local = move_path.place.local; + // a) A return value _0 will eventually be used + // Example: + // fn f() -> Droppy { + // let _x = Droppy; + // Droppy + // } + // _0 holds the literal `Droppy` and rightfully `_x` has to be dropped first + if dropped_local == Local::ZERO { + debug!(?dropped_local, "skip return value"); + to_exclude.insert(path_idx); + continue; + } + // b) If we are analysing a closure, the captures are still dropped last. + // This is part of the closure capture lifetime contract. + // They are similar to the return value _0 with respect to lifetime rules. + if is_closure_like && matches!(dropped_local, ty::CAPTURE_STRUCT_LOCAL) { + debug!(?dropped_local, "skip closure captures"); + to_exclude.insert(path_idx); + continue; + } + // c) Sometimes we collect places that are projections into the BID locals, + // so they are considered dropped now. + // Example: + // struct NotVeryDroppy(Droppy); + // impl Drop for Droppy {..} + // fn f() -> NotVeryDroppy { + // let x = NotVeryDroppy(droppy()); + // { + // let y: Droppy = x.0; + // NotVeryDroppy(y) + // } + // } + // `y` takes `x.0`, which invalidates `x` as a complete `NotVeryDroppy` + // so there is no point in linting against `x` any more. + if place_descendent_of_bids(path_idx, &move_data, &bid_places) { + debug!(?dropped_local, "skip descendent of bids"); + to_exclude.insert(path_idx); + continue; + } + let observer_ty = move_path.place.ty(body, tcx).ty; + // d) The collected local has no custom destructor that passes our ecosystem filter. + if ty_dropped_components + .entry(observer_ty) + .or_insert_with(|| { + extract_component_with_significant_dtor(tcx, param_env, observer_ty) + }) + .is_empty() + { + debug!(?dropped_local, "skip non-droppy types"); + to_exclude.insert(path_idx); + continue; + } + } + // Suppose that all BIDs point into the same local, + // we can remove the this local from the observed drops, + // so that we can focus our diagnosis more on the others. + if candidates.iter().all(|&(_, place)| candidates[0].1.local == place.local) { + for path_idx in all_locals_dropped.iter() { + if move_data.move_paths[path_idx].place.local == candidates[0].1.local { + to_exclude.insert(path_idx); + } + } + } + all_locals_dropped.subtract(&to_exclude); + } + if all_locals_dropped.is_empty() { + // No drop effect is observable, so let us move on. + continue; + } + + // ## The final work to assemble the diagnosis ## + // First collect or generate fresh names for local variable bindings and temporary values. + let local_names = assign_observables_names( + all_locals_dropped + .iter() + .map(|path_idx| move_data.move_paths[path_idx].place.local) + .chain(candidates.iter().map(|(_, place)| place.local)), + &locals_with_user_names, + ); + + let mut lint_root = None; + let mut local_labels = vec![]; + // We now collect the types with custom destructors. + for &(_, place) in candidates { + let linted_local_decl = &body.local_decls[place.local]; + let Some(&(ref name, is_generated_name)) = local_names.get(&place.local) else { + bug!("a name should have been assigned") + }; + let name = name.as_str(); + + if lint_root.is_none() + && let ClearCrossCrate::Set(data) = + &body.source_scopes[linted_local_decl.source_info.scope].local_data + { + lint_root = Some(data.lint_root); + } + + // Collect spans of the custom destructors. + let mut seen_dyn = false; + let destructors = ty_dropped_components + .get(&linted_local_decl.ty) + .unwrap() + .iter() + .filter_map(|&ty| { + if let Some(span) = ty_dtor_span(tcx, ty) { + Some(DestructorLabel { span, name, dtor_kind: "concrete" }) + } else if matches!(ty.kind(), ty::Dynamic(..)) { + if seen_dyn { + None + } else { + seen_dyn = true; + Some(DestructorLabel { span: DUMMY_SP, name, dtor_kind: "dyn" }) + } + } else { + None + } + }) + .collect(); + local_labels.push(LocalLabel { + span: linted_local_decl.source_info.span, + destructors, + name, + is_generated_name, + is_dropped_first_edition_2024: true, + }); + } + + // Similarly, custom destructors of the observed drops. + for path_idx in all_locals_dropped.iter() { + let place = &move_data.move_paths[path_idx].place; + // We are not using the type of the local because the drop may be partial. + let observer_ty = place.ty(body, tcx).ty; + + let observer_local_decl = &body.local_decls[place.local]; + let Some(&(ref name, is_generated_name)) = local_names.get(&place.local) else { + bug!("a name should have been assigned") + }; + let name = name.as_str(); + + let mut seen_dyn = false; + let destructors = extract_component_with_significant_dtor(tcx, param_env, observer_ty) + .into_iter() + .filter_map(|ty| { + if let Some(span) = ty_dtor_span(tcx, ty) { + Some(DestructorLabel { span, name, dtor_kind: "concrete" }) + } else if matches!(ty.kind(), ty::Dynamic(..)) { + if seen_dyn { + None + } else { + seen_dyn = true; + Some(DestructorLabel { span: DUMMY_SP, name, dtor_kind: "dyn" }) + } + } else { + None + } + }) + .collect(); + local_labels.push(LocalLabel { + span: observer_local_decl.source_info.span, + destructors, + name, + is_generated_name, + is_dropped_first_edition_2024: false, + }); + } + + let span = local_labels[0].span; + tcx.emit_node_span_lint( + lint::builtin::TAIL_EXPR_DROP_ORDER, + lint_root.unwrap_or(CRATE_HIR_ID), + span, + TailExprDropOrderLint { local_labels, drop_span, _epilogue: () }, + ); + } +} + +/// Extract binding names if available for diagnosis +fn collect_user_names(body: &Body<'_>) -> IndexMap { + let mut names = IndexMap::default(); + for var_debug_info in &body.var_debug_info { + if let mir::VarDebugInfoContents::Place(place) = &var_debug_info.value + && let Some(local) = place.local_or_deref_local() + { + names.entry(local).or_insert(var_debug_info.name); + } + } + names +} + +/// Assign names for anonymous or temporary values for diagnosis +fn assign_observables_names( + locals: impl IntoIterator, + user_names: &IndexMap, +) -> IndexMap { + let mut names = IndexMap::default(); + let mut assigned_names = FxHashSet::default(); + let mut idx = 0u64; + let mut fresh_name = || { + idx += 1; + (format!("#{idx}"), true) + }; + for local in locals { + let name = if let Some(name) = user_names.get(&local) { + let name = name.as_str(); + if assigned_names.contains(name) { fresh_name() } else { (name.to_owned(), false) } + } else { + fresh_name() + }; + assigned_names.insert(name.0.clone()); + names.insert(local, name); + } + names +} + +#[derive(LintDiagnostic)] +#[diag(mir_transform_tail_expr_drop_order)] +struct TailExprDropOrderLint<'a> { + #[subdiagnostic] + local_labels: Vec>, + #[label(mir_transform_drop_location)] + drop_span: Option, + #[note(mir_transform_note_epilogue)] + _epilogue: (), +} + +struct LocalLabel<'a> { + span: Span, + name: &'a str, + is_generated_name: bool, + is_dropped_first_edition_2024: bool, + destructors: Vec>, +} + +/// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order +impl Subdiagnostic for LocalLabel<'_> { + fn add_to_diag_with< + G: rustc_errors::EmissionGuarantee, + F: rustc_errors::SubdiagMessageOp, + >( + self, + diag: &mut rustc_errors::Diag<'_, G>, + f: &F, + ) { + diag.arg("name", self.name); + diag.arg("is_generated_name", self.is_generated_name); + diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024); + let msg = f(diag, crate::fluent_generated::mir_transform_tail_expr_local.into()); + diag.span_label(self.span, msg); + for dtor in self.destructors { + dtor.add_to_diag_with(diag, f); + } + let msg = f(diag, crate::fluent_generated::mir_transform_label_local_epilogue.into()); + diag.span_label(self.span, msg); + } +} + +#[derive(Subdiagnostic)] +#[note(mir_transform_tail_expr_dtor)] +struct DestructorLabel<'a> { + #[primary_span] + span: Span, + dtor_kind: &'static str, + name: &'a str, +} diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 55394e93a5c..fd49e956f43 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -92,6 +92,7 @@ impl RemoveNoopLandingPads { | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) | StatementKind::ConstEvalCounter + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => { // These are all noops in a landing pad } diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 2f723bccc19..6fd70fbe9b0 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -125,6 +125,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { StatementKind::Coverage(_) | StatementKind::Intrinsic(_) | StatementKind::Nop + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::ConstEvalCounter => None, }; if let Some(place_for_ty) = place_for_ty diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 7ed43547e11..4f312ed2aaa 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -523,7 +523,8 @@ impl<'tcx> Visitor<'tcx> for UsedLocals { } StatementKind::SetDiscriminant { ref place, variant_index: _ } - | StatementKind::Deinit(ref place) => { + | StatementKind::Deinit(ref place) + | StatementKind::BackwardIncompatibleDropHint { ref place, reason: _ } => { self.visit_lhs(place, location); } } @@ -560,6 +561,7 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod StatementKind::Assign(box (place, _)) => used_locals.is_used(place.local), StatementKind::SetDiscriminant { ref place, .. } + | StatementKind::BackwardIncompatibleDropHint { ref place, reason: _ } | StatementKind::Deinit(ref place) => used_locals.is_used(place.local), StatementKind::Nop => false, _ => true, @@ -587,6 +589,20 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> { self.tcx } + fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { + if let StatementKind::BackwardIncompatibleDropHint { place, reason: _ } = + &mut statement.kind + { + self.visit_local( + &mut place.local, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location, + ); + } else { + self.super_statement(statement, location); + } + } + fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) { *l = self.map[*l].unwrap(); } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 724238ecfc9..1739fdcc9af 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -343,6 +343,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { | StatementKind::Intrinsic(_) | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => {} } @@ -1493,6 +1494,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | StatementKind::Coverage(_) | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => {} } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 820d8a6be25..fcdf8703b14 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -151,6 +151,10 @@ impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> { mir::StatementKind::ConstEvalCounter => { stable_mir::mir::StatementKind::ConstEvalCounter } + // BackwardIncompatibleDropHint has no semantics, so it is translated to Nop. + mir::StatementKind::BackwardIncompatibleDropHint { .. } => { + stable_mir::mir::StatementKind::Nop + } mir::StatementKind::Nop => stable_mir::mir::StatementKind::Nop, } } diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 03ab3a55486..469a4ac3e41 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::util::{AlwaysRequiresDrop, needs_drop_components}; use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt}; use rustc_session::Limit; use rustc_span::sym; -use tracing::debug; +use tracing::{debug, instrument}; use crate::errors::NeedsDropOverflow; @@ -23,7 +23,7 @@ fn needs_drop_raw<'tcx>( // needs drop. let adt_has_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant); - let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_dtor, false) + let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_dtor, false, false) .filter(filter_array_elements(tcx, query.typing_env)) .next() .is_some(); @@ -41,7 +41,7 @@ fn needs_async_drop_raw<'tcx>( // it needs async drop. let adt_has_async_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant); - let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_async_dtor, false) + let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_async_dtor, false, false) .filter(filter_array_elements(tcx, query.typing_env)) .next() .is_some(); @@ -77,6 +77,7 @@ fn has_significant_drop_raw<'tcx>( query.typing_env, adt_consider_insignificant_dtor(tcx), true, + false, ) .filter(filter_array_elements(tcx, query.typing_env)) .next() @@ -88,8 +89,8 @@ fn has_significant_drop_raw<'tcx>( struct NeedsDropTypes<'tcx, F> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - // Whether to reveal coroutine witnesses, this is set - // to `false` unless we compute `needs_drop` for a coroutine witness. + /// Whether to reveal coroutine witnesses, this is set + /// to `false` unless we compute `needs_drop` for a coroutine witness. reveal_coroutine_witnesses: bool, query_ty: Ty<'tcx>, seen_tys: FxHashSet>, @@ -100,6 +101,9 @@ struct NeedsDropTypes<'tcx, F> { unchecked_tys: Vec<(Ty<'tcx>, usize)>, recursion_limit: Limit, adt_components: F, + /// Set this to true if an exhaustive list of types involved in + /// drop obligation is requested. + exhaustive: bool, } impl<'tcx, F> NeedsDropTypes<'tcx, F> { @@ -107,6 +111,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, + exhaustive: bool, adt_components: F, ) -> Self { let mut seen_tys = FxHashSet::default(); @@ -114,14 +119,22 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { Self { tcx, typing_env, - reveal_coroutine_witnesses: false, + reveal_coroutine_witnesses: exhaustive, seen_tys, query_ty: ty, unchecked_tys: vec![(ty, 0)], recursion_limit: tcx.recursion_limit(), adt_components, + exhaustive, } } + + /// Called when `ty` is found to always require drop. + /// If the exhaustive flag is true, then `Ok(ty)` is returned like any other type. + /// Otherwise, `Err(AlwaysRequireDrop)` is returned, which will cause iteration to abort. + fn always_drop_component(&self, ty: Ty<'tcx>) -> NeedsDropResult> { + if self.exhaustive { Ok(ty) } else { Err(AlwaysRequiresDrop) } + } } impl<'tcx, F, I> Iterator for NeedsDropTypes<'tcx, F> @@ -131,19 +144,22 @@ where { type Item = NeedsDropResult>; + #[instrument(level = "debug", skip(self), ret)] fn next(&mut self) -> Option>> { let tcx = self.tcx; while let Some((ty, level)) = self.unchecked_tys.pop() { + debug!(?ty, "needs_drop_components: inspect"); if !self.recursion_limit.value_within_limit(level) { // Not having a `Span` isn't great. But there's hopefully some other // recursion limit error as well. + debug!("needs_drop_components: recursion limit exceeded"); tcx.dcx().emit_err(NeedsDropOverflow { query_ty: self.query_ty }); - return Some(Err(AlwaysRequiresDrop)); + return Some(self.always_drop_component(ty)); } let components = match needs_drop_components(tcx, ty) { - Err(e) => return Some(Err(e)), + Err(AlwaysRequiresDrop) => return Some(self.always_drop_component(ty)), Ok(components) => components, }; debug!("needs_drop_components({:?}) = {:?}", ty, components); @@ -171,7 +187,7 @@ where if self.reveal_coroutine_witnesses { queue_type(self, args.as_coroutine().witness()); } else { - return Some(Err(AlwaysRequiresDrop)); + return Some(self.always_drop_component(ty)); } } ty::CoroutineWitness(def_id, args) => { @@ -186,7 +202,7 @@ where } } - _ if component.is_copy_modulo_regions(tcx, self.typing_env) => (), + _ if component.is_copy_modulo_regions(tcx, self.typing_env) => {} ty::Closure(_, args) => { for upvar in args.as_closure().upvar_tys() { @@ -205,7 +221,9 @@ where // impl then check whether the field types need `Drop`. ty::Adt(adt_def, args) => { let tys = match (self.adt_components)(adt_def, args) { - Err(e) => return Some(Err(e)), + Err(AlwaysRequiresDrop) => { + return Some(self.always_drop_component(ty)); + } Ok(tys) => tys, }; for required_ty in tys { @@ -230,7 +248,8 @@ where } ty::Foreign(_) | ty::Dynamic(..) => { - return Some(Err(AlwaysRequiresDrop)); + debug!("needs_drop_components: foreign or dynamic"); + return Some(self.always_drop_component(ty)); } ty::Bool @@ -280,6 +299,7 @@ fn drop_tys_helper<'tcx>( typing_env: ty::TypingEnv<'tcx>, adt_has_dtor: impl Fn(ty::AdtDef<'tcx>) -> Option, only_significant: bool, + exhaustive: bool, ) -> impl Iterator>> { fn with_query_cache<'tcx>( tcx: TyCtxt<'tcx>, @@ -343,7 +363,7 @@ fn drop_tys_helper<'tcx>( .map(|v| v.into_iter()) }; - NeedsDropTypes::new(tcx, typing_env, ty, adt_components) + NeedsDropTypes::new(tcx, typing_env, ty, exhaustive, adt_components) } fn adt_consider_insignificant_dtor<'tcx>( @@ -384,6 +404,7 @@ fn adt_drop_tys<'tcx>( ty::TypingEnv::non_body_analysis(tcx, def_id), adt_has_dtor, false, + false, ) .collect::, _>>() .map(|components| tcx.mk_type_list(&components)) @@ -401,11 +422,31 @@ fn adt_significant_drop_tys( ty::TypingEnv::non_body_analysis(tcx, def_id), adt_consider_insignificant_dtor(tcx), true, + false, ) .collect::, _>>() .map(|components| tcx.mk_type_list(&components)) } +#[instrument(level = "debug", skip(tcx), ret)] +fn list_significant_drop_tys<'tcx>( + tcx: TyCtxt<'tcx>, + ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, +) -> &'tcx ty::List> { + tcx.mk_type_list( + &drop_tys_helper( + tcx, + ty.value, + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: ty.param_env }, + adt_consider_insignificant_dtor(tcx), + true, + true, + ) + .filter_map(|res| res.ok()) + .collect::>(), + ) +} + pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { needs_drop_raw, @@ -413,6 +454,7 @@ pub(crate) fn provide(providers: &mut Providers) { has_significant_drop_raw, adt_drop_tys, adt_significant_drop_tys, + list_significant_drop_tys, ..*providers }; } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index abadca71400..345c46f944a 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -233,6 +233,7 @@ fn check_statement<'tcx>( | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) | StatementKind::ConstEvalCounter + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => Ok(()), } } diff --git a/tests/ui/drop/lint-tail-expr-drop-order-gated.rs b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs index fde542c756f..508e7bdbf99 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order-gated.rs +++ b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs @@ -1,9 +1,10 @@ -// This test is to demonstrate that the lint is gated behind Edition and -// is triggered only for Edition 2021 and before. +// This test ensures that `tail_expr_drop_order` does not activate in case Edition 2024 is used +// because this is a migration lint. +// Only `cargo fix --edition 2024` shall activate this lint. //@ check-pass -//@ edition: 2024 //@ compile-flags: -Z unstable-options +//@ edition: 2024 #![deny(tail_expr_drop_order)] diff --git a/tests/ui/drop/lint-tail-expr-drop-order.rs b/tests/ui/drop/lint-tail-expr-drop-order.rs index d61abae5187..0fabc1f085c 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order.rs +++ b/tests/ui/drop/lint-tail-expr-drop-order.rs @@ -1,13 +1,26 @@ -//@ edition: 2021 - // Edition 2024 lint for change in drop order at tail expression // This lint is to capture potential change in program semantics // due to implementation of RFC 3606 +//@ edition: 2021 +//@ build-fail -#![deny(tail_expr_drop_order)] +#![deny(tail_expr_drop_order)] //~ NOTE: the lint level is defined here +#![allow(dropping_copy_types)] struct LoudDropper; impl Drop for LoudDropper { + //~^ NOTE: `#1` invokes this custom destructor + //~| NOTE: `x` invokes this custom destructor + //~| NOTE: `#1` invokes this custom destructor + //~| NOTE: `x` invokes this custom destructor + //~| NOTE: `#1` invokes this custom destructor + //~| NOTE: `x` invokes this custom destructor + //~| NOTE: `#1` invokes this custom destructor + //~| NOTE: `x` invokes this custom destructor + //~| NOTE: `#1` invokes this custom destructor + //~| NOTE: `future` invokes this custom destructor + //~| NOTE: `_x` invokes this custom destructor + //~| NOTE: `#1` invokes this custom destructor fn drop(&mut self) { // This destructor should be considered significant because it is a custom destructor // and we will assume that the destructor can generate side effects arbitrarily so that @@ -23,30 +36,70 @@ impl LoudDropper { fn should_lint() -> i32 { let x = LoudDropper; + //~^ NOTE: `x` calls a custom destructor + //~| NOTE: `x` will be dropped later as of Edition 2024 // Should lint x.get() + LoudDropper.get() - //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 + //~^ ERROR: relative drop order changing in Rust 2024 + //~| NOTE: this value will be stored in a temporary; let us call it `#1` + //~| NOTE: up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 //~| WARN: this changes meaning in Rust 2024 + //~| NOTE: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects + //~| NOTE: for more information, see issue #123739 } +//~^ NOTE: now the temporary value is dropped here, before the local variables in the block or statement -fn should_lint_closure() -> impl FnOnce() -> i32 { +fn should_not_lint_closure() -> impl FnOnce() -> i32 { let x = LoudDropper; - move || x.get() + LoudDropper.get() - //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 - //~| WARN: this changes meaning in Rust 2024 + move || { + // Should not lint because ... + x.get() + LoudDropper.get() + } + // ^ closure captures like `x` are always dropped last by contract +} + +fn should_lint_in_nested_items() { + fn should_lint_me() -> i32 { + let x = LoudDropper; + //~^ NOTE: `x` calls a custom destructor + //~| NOTE: `x` will be dropped later as of Edition 2024 + // Should lint + x.get() + LoudDropper.get() + //~^ ERROR: relative drop order changing in Rust 2024 + //~| NOTE: this value will be stored in a temporary; let us call it `#1` + //~| NOTE: up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| NOTE: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects + //~| NOTE: for more information, see issue #123739 + } + //~^ NOTE: now the temporary value is dropped here, before the local variables in the block or statement } +fn should_not_lint_params(x: LoudDropper) -> i32 { + // Should not lint because ... + x.get() + LoudDropper.get() +} +// ^ function parameters like `x` are always dropped last + fn should_not_lint() -> i32 { let x = LoudDropper; // Should not lint x.get() } -fn should_not_lint_in_nested_block() -> i32 { +fn should_lint_in_nested_block() -> i32 { let x = LoudDropper; - // Should not lint because Edition 2021 drops temporaries in blocks earlier already + //~^ NOTE: `x` calls a custom destructor + //~| NOTE: `x` will be dropped later as of Edition 2024 { LoudDropper.get() } + //~^ ERROR: relative drop order changing in Rust 2024 + //~| NOTE: this value will be stored in a temporary; let us call it `#1` + //~| NOTE: up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| NOTE: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects + //~| NOTE: for more information, see issue #123739 } +//~^ NOTE: now the temporary value is dropped here, before the local variables in the block or statement fn should_not_lint_in_match_arm() -> i32 { let x = LoudDropper; @@ -56,14 +109,144 @@ fn should_not_lint_in_match_arm() -> i32 { } } -fn should_lint_in_nested_items() { - fn should_lint_me() -> i32 { +fn should_not_lint_when_consumed() -> (LoudDropper, i32) { + let x = LoudDropper; + // Should not lint because `LoudDropper` is consumed by the return value + (LoudDropper, x.get()) +} + +struct MyAdt { + a: LoudDropper, + b: LoudDropper, +} + +fn should_not_lint_when_consumed_in_ctor() -> MyAdt { + let a = LoudDropper; + // Should not lint + MyAdt { a, b: LoudDropper } +} + +fn should_not_lint_when_moved() -> i32 { + let x = LoudDropper; + drop(x); + // Should not lint because `x` is not live + LoudDropper.get() +} + +fn should_lint_into_async_body() -> i32 { + async fn f() { + async fn f() {} let x = LoudDropper; - // Should lint - x.get() + LoudDropper.get() - //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 - //~| WARN: this changes meaning in Rust 2024 + f().await; + drop(x); + } + + let future = f(); + //~^ NOTE: `future` calls a custom destructor + //~| NOTE: `future` will be dropped later as of Edition 2024 + LoudDropper.get() + //~^ ERROR: relative drop order changing in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| NOTE: this value will be stored in a temporary; let us call it `#1` + //~| NOTE: up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 + //~| NOTE: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects + //~| NOTE: for more information, see issue #123739 +} +//~^ NOTE: now the temporary value is dropped here, before the local variables in the block or statement + +fn should_lint_generics() -> &'static str { + fn extract(_: &T) -> &'static str { + todo!() + } + let x = T::default(); + //~^ NOTE: `x` calls a custom destructor + //~| NOTE: `x` will be dropped later as of Edition 2024 + extract(&T::default()) + //~^ ERROR: relative drop order changing in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| NOTE: this value will be stored in a temporary; let us call it `#1` + //~| NOTE: up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 + //~| NOTE: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects + //~| NOTE: for more information, see issue #123739 +} +//~^ NOTE: now the temporary value is dropped here, before the local variables in the block or statement + +fn should_lint_adt() -> i32 { + let x: Result = Ok(LoudDropper); + //~^ NOTE: `x` calls a custom destructor + //~| NOTE: `x` will be dropped later as of Edition 2024 + LoudDropper.get() + //~^ ERROR: relative drop order changing in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| NOTE: this value will be stored in a temporary; let us call it `#1` + //~| NOTE: up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 + //~| NOTE: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects + //~| NOTE: for more information, see issue #123739 +} +//~^ NOTE: now the temporary value is dropped here, before the local variables in the block or statement + +fn should_not_lint_insign_dtor() -> i32 { + let x = String::new(); + LoudDropper.get() +} + +fn should_lint_with_dtor_span() -> i32 { + struct LoudDropper3; + impl Drop for LoudDropper3 { + //~^ NOTE: `#1` invokes this custom destructor + fn drop(&mut self) { + println!("loud drop"); + } } + impl LoudDropper3 { + fn get(&self) -> i32 { + 0 + } + } + struct LoudDropper2; + impl Drop for LoudDropper2 { + //~^ NOTE: `x` invokes this custom destructor + fn drop(&mut self) { + println!("loud drop"); + } + } + impl LoudDropper2 { + fn get(&self) -> i32 { + 0 + } + } + + let x = LoudDropper2; + //~^ NOTE: `x` calls a custom destructor + //~| NOTE: `x` will be dropped later as of Edition 2024 + LoudDropper3.get() + //~^ ERROR: relative drop order changing in Rust 2024 + //~| NOTE: this value will be stored in a temporary; let us call it `#1` + //~| NOTE: up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| NOTE: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects + //~| NOTE: for more information, see issue #123739 +} +//~^ NOTE: now the temporary value is dropped here, before the local variables in the block or statement + +fn should_lint_with_transient_drops() { + drop(( + { + LoudDropper.get() + //~^ ERROR: relative drop order changing in Rust 2024 + //~| NOTE: this value will be stored in a temporary; let us call it `#1` + //~| NOTE: up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| NOTE: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects + //~| NOTE: for more information, see issue #123739 + }, + { + let _x = LoudDropper; + //~^ NOTE: `_x` calls a custom destructor + //~| NOTE: `_x` will be dropped later as of Edition 2024 + }, + )); + //~^ NOTE: now the temporary value is dropped here, before the local variables in the block or statement } fn main() {} diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr index 6775c4ce6d1..f0da24605e6 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order.stderr +++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr @@ -1,42 +1,335 @@ -error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 - --> $DIR/lint-tail-expr-drop-order.rs:27:15 +error: relative drop order changing in Rust 2024 + --> $DIR/lint-tail-expr-drop-order.rs:42:15 | LL | let x = LoudDropper; - | - these values have significant drop implementation and will observe changes in drop order under Edition 2024 -LL | // Should lint + | - + | | + | `x` calls a custom destructor + | `x` will be dropped later as of Edition 2024 +... LL | x.get() + LoudDropper.get() | ^^^^^^^^^^^ + | | + | this value will be stored in a temporary; let us call it `#1` + | up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 +... +LL | } + | - now the temporary value is dropped here, before the local variables in the block or statement | = warning: this changes meaning in Rust 2024 = note: for more information, see issue #123739 +note: `#1` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ +note: `x` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages note: the lint level is defined here --> $DIR/lint-tail-expr-drop-order.rs:7:9 | LL | #![deny(tail_expr_drop_order)] | ^^^^^^^^^^^^^^^^^^^^ -error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 - --> $DIR/lint-tail-expr-drop-order.rs:34:23 +error: relative drop order changing in Rust 2024 + --> $DIR/lint-tail-expr-drop-order.rs:67:19 + | +LL | let x = LoudDropper; + | - + | | + | `x` calls a custom destructor + | `x` will be dropped later as of Edition 2024 +... +LL | x.get() + LoudDropper.get() + | ^^^^^^^^^^^ + | | + | this value will be stored in a temporary; let us call it `#1` + | up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 +... +LL | } + | - now the temporary value is dropped here, before the local variables in the block or statement + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #123739 +note: `#1` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ +note: `x` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + +error: relative drop order changing in Rust 2024 + --> $DIR/lint-tail-expr-drop-order.rs:94:7 | LL | let x = LoudDropper; - | - these values have significant drop implementation and will observe changes in drop order under Edition 2024 -LL | move || x.get() + LoudDropper.get() - | ^^^^^^^^^^^ + | - + | | + | `x` calls a custom destructor + | `x` will be dropped later as of Edition 2024 +... +LL | { LoudDropper.get() } + | ^^^^^^^^^^^ + | | + | this value will be stored in a temporary; let us call it `#1` + | up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 +... +LL | } + | - now the temporary value is dropped here, before the local variables in the block or statement | = warning: this changes meaning in Rust 2024 = note: for more information, see issue #123739 +note: `#1` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ +note: `x` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages -error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021 - --> $DIR/lint-tail-expr-drop-order.rs:63:19 +error: relative drop order changing in Rust 2024 + --> $DIR/lint-tail-expr-drop-order.rs:147:5 | -LL | let x = LoudDropper; - | - these values have significant drop implementation and will observe changes in drop order under Edition 2024 -LL | // Should lint -LL | x.get() + LoudDropper.get() - | ^^^^^^^^^^^ +LL | let future = f(); + | ------ + | | + | `future` calls a custom destructor + | `future` will be dropped later as of Edition 2024 +... +LL | LoudDropper.get() + | ^^^^^^^^^^^ + | | + | this value will be stored in a temporary; let us call it `#1` + | up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 +... +LL | } + | - now the temporary value is dropped here, before the local variables in the block or statement | = warning: this changes meaning in Rust 2024 = note: for more information, see issue #123739 +note: `#1` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ +note: `future` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + +error: relative drop order changing in Rust 2024 + --> $DIR/lint-tail-expr-drop-order.rs:164:14 + | +LL | let x = T::default(); + | - + | | + | `x` calls a custom destructor + | `x` will be dropped later as of Edition 2024 +... +LL | extract(&T::default()) + | ^^^^^^^^^^^^ + | | + | this value will be stored in a temporary; let us call it `#1` + | up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 +... +LL | } + | - now the temporary value is dropped here, before the local variables in the block or statement + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #123739 + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + +error: relative drop order changing in Rust 2024 + --> $DIR/lint-tail-expr-drop-order.rs:178:5 + | +LL | let x: Result = Ok(LoudDropper); + | - + | | + | `x` calls a custom destructor + | `x` will be dropped later as of Edition 2024 +... +LL | LoudDropper.get() + | ^^^^^^^^^^^ + | | + | this value will be stored in a temporary; let us call it `#1` + | up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 +... +LL | } + | - now the temporary value is dropped here, before the local variables in the block or statement + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #123739 +note: `#1` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ +note: `x` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + +error: relative drop order changing in Rust 2024 + --> $DIR/lint-tail-expr-drop-order.rs:222:5 + | +LL | let x = LoudDropper2; + | - + | | + | `x` calls a custom destructor + | `x` will be dropped later as of Edition 2024 +... +LL | LoudDropper3.get() + | ^^^^^^^^^^^^ + | | + | this value will be stored in a temporary; let us call it `#1` + | up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 +... +LL | } + | - now the temporary value is dropped here, before the local variables in the block or statement + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #123739 +note: `#1` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:195:5 + | +LL | / impl Drop for LoudDropper3 { +LL | | +LL | | fn drop(&mut self) { +LL | | println!("loud drop"); +LL | | } +LL | | } + | |_____^ +note: `x` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:207:5 + | +LL | / impl Drop for LoudDropper2 { +LL | | +LL | | fn drop(&mut self) { +LL | | println!("loud drop"); +LL | | } +LL | | } + | |_____^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + +error: relative drop order changing in Rust 2024 + --> $DIR/lint-tail-expr-drop-order.rs:235:13 + | +LL | LoudDropper.get() + | ^^^^^^^^^^^ + | | + | this value will be stored in a temporary; let us call it `#1` + | up until Edition 2021 `#1` is dropped last but will be dropped earlier in Edition 2024 +... +LL | let _x = LoudDropper; + | -- + | | + | `_x` calls a custom destructor + | `_x` will be dropped later as of Edition 2024 +... +LL | )); + | - now the temporary value is dropped here, before the local variables in the block or statement + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #123739 +note: `#1` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ +note: `_x` invokes this custom destructor + --> $DIR/lint-tail-expr-drop-order.rs:11:1 + | +LL | / impl Drop for LoudDropper { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages -error: aborting due to 3 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/thir-print/thir-flat-const-variant.stdout b/tests/ui/thir-print/thir-flat-const-variant.stdout index 1840be7885b..5588cfdfa5c 100644 --- a/tests/ui/thir-print/thir-flat-const-variant.stdout +++ b/tests/ui/thir-print/thir-flat-const-variant.stdout @@ -11,9 +11,12 @@ Thir { fields: [], }, ty: (), - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:12:32: 12:34 (#0), }, Expr { @@ -25,9 +28,12 @@ Thir { value: e0, }, ty: (), - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:12:32: 12:34 (#0), }, Expr { @@ -47,9 +53,12 @@ Thir { }, ), ty: Foo, - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:12:23: 12:35 (#0), }, Expr { @@ -61,9 +70,12 @@ Thir { value: e2, }, ty: Foo, - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:12:23: 12:35 (#0), }, ], @@ -84,9 +96,12 @@ Thir { fields: [], }, ty: (), - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:13:33: 13:35 (#0), }, Expr { @@ -98,9 +113,12 @@ Thir { value: e0, }, ty: (), - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:13:33: 13:35 (#0), }, Expr { @@ -120,9 +138,12 @@ Thir { }, ), ty: Foo, - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:13:23: 13:36 (#0), }, Expr { @@ -134,9 +155,12 @@ Thir { value: e2, }, ty: Foo, - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:13:23: 13:36 (#0), }, ], @@ -157,9 +181,12 @@ Thir { fields: [], }, ty: (), - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:14:33: 14:35 (#0), }, Expr { @@ -171,9 +198,12 @@ Thir { value: e0, }, ty: (), - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:14:33: 14:35 (#0), }, Expr { @@ -193,9 +223,12 @@ Thir { }, ), ty: Foo, - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:14:24: 14:36 (#0), }, Expr { @@ -207,9 +240,12 @@ Thir { value: e2, }, ty: Foo, - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:14:24: 14:36 (#0), }, ], @@ -230,9 +266,12 @@ Thir { fields: [], }, ty: (), - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:15:34: 15:36 (#0), }, Expr { @@ -244,9 +283,12 @@ Thir { value: e0, }, ty: (), - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:15:34: 15:36 (#0), }, Expr { @@ -266,9 +308,12 @@ Thir { }, ), ty: Foo, - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:15:24: 15:37 (#0), }, Expr { @@ -280,9 +325,12 @@ Thir { value: e2, }, ty: Foo, - temp_lifetime: Some( - Node(3), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(3), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:15:24: 15:37 (#0), }, ], @@ -312,9 +360,12 @@ Thir { block: b0, }, ty: (), - temp_lifetime: Some( - Node(2), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(2), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0), }, Expr { @@ -326,9 +377,12 @@ Thir { value: e0, }, ty: (), - temp_lifetime: Some( - Node(2), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(2), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0), }, ], diff --git a/tests/ui/thir-print/thir-flat.stdout b/tests/ui/thir-print/thir-flat.stdout index a31d08adab6..59cecfe511c 100644 --- a/tests/ui/thir-print/thir-flat.stdout +++ b/tests/ui/thir-print/thir-flat.stdout @@ -20,9 +20,12 @@ Thir { block: b0, }, ty: (), - temp_lifetime: Some( - Node(2), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(2), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat.rs:4:15: 4:17 (#0), }, Expr { @@ -34,9 +37,12 @@ Thir { value: e0, }, ty: (), - temp_lifetime: Some( - Node(2), - ), + temp_lifetime: TempLifetime { + temp_lifetime: Some( + Node(2), + ), + backwards_incompatible: None, + }, span: $DIR/thir-flat.rs:4:15: 4:17 (#0), }, ], diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout index 8cff7887661..a9d6985928a 100644 --- a/tests/ui/thir-print/thir-tree-match.stdout +++ b/tests/ui/thir-print/thir-tree-match.stdout @@ -26,7 +26,7 @@ params: [ body: Expr { ty: bool - temp_lifetime: Some(Node(26)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) kind: Scope { @@ -35,7 +35,7 @@ body: value: Expr { ty: bool - temp_lifetime: Some(Node(26)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) kind: Block { @@ -47,7 +47,7 @@ body: expr: Expr { ty: bool - temp_lifetime: Some(Node(26)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) kind: Scope { @@ -56,14 +56,14 @@ body: value: Expr { ty: bool - temp_lifetime: Some(Node(26)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) kind: Match { scrutinee: Expr { ty: Foo - temp_lifetime: Some(Node(26)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) kind: Scope { @@ -72,7 +72,7 @@ body: value: Expr { ty: Foo - temp_lifetime: Some(Node(26)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) kind: VarRef { @@ -123,7 +123,7 @@ body: body: Expr { ty: bool - temp_lifetime: Some(Node(13)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(13)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) kind: Scope { @@ -132,7 +132,7 @@ body: value: Expr { ty: bool - temp_lifetime: Some(Node(13)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(13)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) kind: Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false) @@ -175,7 +175,7 @@ body: body: Expr { ty: bool - temp_lifetime: Some(Node(19)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(19)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) kind: Scope { @@ -184,7 +184,7 @@ body: value: Expr { ty: bool - temp_lifetime: Some(Node(19)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(19)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) kind: Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false) @@ -219,7 +219,7 @@ body: body: Expr { ty: bool - temp_lifetime: Some(Node(24)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) kind: Scope { @@ -228,7 +228,7 @@ body: value: Expr { ty: bool - temp_lifetime: Some(Node(24)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) kind: Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false) @@ -257,7 +257,7 @@ params: [ body: Expr { ty: () - temp_lifetime: Some(Node(2)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) kind: Scope { @@ -266,7 +266,7 @@ body: value: Expr { ty: () - temp_lifetime: Some(Node(2)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) kind: Block { diff --git a/tests/ui/thir-print/thir-tree.stdout b/tests/ui/thir-print/thir-tree.stdout index ef6db368dbe..b39581ad841 100644 --- a/tests/ui/thir-print/thir-tree.stdout +++ b/tests/ui/thir-print/thir-tree.stdout @@ -4,7 +4,7 @@ params: [ body: Expr { ty: () - temp_lifetime: Some(Node(2)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } span: $DIR/thir-tree.rs:4:15: 4:17 (#0) kind: Scope { @@ -13,7 +13,7 @@ body: value: Expr { ty: () - temp_lifetime: Some(Node(2)) + temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } span: $DIR/thir-tree.rs:4:15: 4:17 (#0) kind: Block { -- cgit 1.4.1-3-g733a5 From 0f8405f702c2b6c2ddd34cf4b6c284e6f2575579 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 20 Nov 2024 11:27:35 +0100 Subject: `ElaborateDrops`: use typing_env directly --- compiler/rustc_mir_dataflow/src/lib.rs | 4 ++-- compiler/rustc_mir_transform/src/elaborate_drops.rs | 18 ++++-------------- 2 files changed, 6 insertions(+), 16 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index ab1453f1ed0..7ef7c541173 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -39,7 +39,7 @@ pub mod value_analysis; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } -pub struct MoveDataParamEnv<'tcx> { +pub struct MoveDataTypingEnv<'tcx> { pub move_data: MoveData<'tcx>, - pub param_env: ty::ParamEnv<'tcx>, + pub typing_env: ty::TypingEnv<'tcx>, } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index b0f041d8722..0c0f3b61977 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -3,7 +3,6 @@ use std::fmt; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_index::IndexVec; use rustc_index::bit_set::BitSet; -use rustc_infer::traits::Reveal; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; @@ -13,7 +12,7 @@ use rustc_mir_dataflow::elaborate_drops::{ use rustc_mir_dataflow::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{ - Analysis, MoveDataParamEnv, ResultsCursor, on_all_children_bits, on_lookup_result_bits, + Analysis, MoveDataTypingEnv, ResultsCursor, on_all_children_bits, on_lookup_result_bits, }; use rustc_span::Span; use tracing::{debug, instrument}; @@ -61,7 +60,7 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { // init/uninit for types that do need dropping. let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env)); let elaborate_patch = { - let env = MoveDataParamEnv { move_data, param_env: typing_env.param_env }; + let env = MoveDataTypingEnv { move_data, typing_env }; let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data) .skipping_unreachable_unwind() @@ -149,7 +148,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> { } fn typing_env(&self) -> ty::TypingEnv<'tcx> { - self.typing_env() + self.env.typing_env } #[instrument(level = "debug", skip(self), ret)] @@ -230,7 +229,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> { struct ElaborateDropsCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, - env: &'a MoveDataParamEnv<'tcx>, + env: &'a MoveDataTypingEnv<'tcx>, init_data: InitializationData<'a, 'tcx>, drop_flags: IndexVec>, patch: MirPatch<'tcx>, @@ -247,15 +246,6 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { &self.env.move_data } - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.env.param_env - } - - fn typing_env(&self) -> ty::TypingEnv<'tcx> { - debug_assert_eq!(self.param_env().reveal(), Reveal::All); - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env() } - } - fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) { let patch = &mut self.patch; debug!("create_drop_flag({:?})", self.body.span); -- cgit 1.4.1-3-g733a5 From a8c8ab1acd0f7a2d8c88ea90f91fad2e1f2092c4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 20 Nov 2024 11:59:52 +0100 Subject: remove remaining references to `Reveal` --- compiler/rustc_codegen_cranelift/src/abi/mod.rs | 18 +++--- compiler/rustc_codegen_cranelift/src/base.rs | 2 +- compiler/rustc_codegen_cranelift/src/common.rs | 18 +++--- .../rustc_codegen_cranelift/src/debuginfo/types.rs | 16 +++-- compiler/rustc_codegen_cranelift/src/global_asm.rs | 2 +- compiler/rustc_codegen_cranelift/src/inline_asm.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 3 +- compiler/rustc_middle/src/query/mod.rs | 9 +-- compiler/rustc_middle/src/ty/instance.rs | 4 +- compiler/rustc_middle/src/ty/layout.rs | 4 +- compiler/rustc_middle/src/ty/util.rs | 4 +- .../src/thir/pattern/const_to_pat.rs | 8 +-- .../rustc_mir_transform/src/known_panics_lint.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 6 +- .../src/post_analysis_normalize.rs | 74 ++++++++++++++++++++++ .../src/remove_unneeded_drops.rs | 3 +- compiler/rustc_mir_transform/src/reveal_all.rs | 73 --------------------- compiler/rustc_mir_transform/src/shim.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 2 +- .../src/solve/normalizes_to/opaque_types.rs | 3 +- compiler/rustc_trait_selection/src/traits/mod.rs | 10 +-- .../rustc_trait_selection/src/traits/normalize.rs | 2 +- compiler/rustc_ty_utils/src/instance.rs | 6 +- compiler/rustc_ty_utils/src/layout.rs | 6 +- compiler/rustc_type_ir/src/predicate.rs | 2 +- compiler/rustc_type_ir/src/ty_kind.rs | 2 +- ...8442.bar.PostAnalysisNormalize.panic-abort.diff | 58 +++++++++++++++++ ...442.bar.PostAnalysisNormalize.panic-unwind.diff | 58 +++++++++++++++++ .../issue_78442.bar.RevealAll.panic-abort.diff | 58 ----------------- .../issue_78442.bar.RevealAll.panic-unwind.diff | 58 ----------------- tests/mir-opt/inline/issue_78442.rs | 2 +- tests/ui/impl-trait/transmute/in-defining-scope.rs | 4 +- tests/ui/mir/validate/needs-reveal-all.rs | 4 +- tests/ui/sanitizer/cfi/can-reveal-opaques.rs | 2 +- tests/ui/type-alias-impl-trait/in-where-clause.rs | 2 +- .../struct-assignment-validity.rs | 2 +- 37 files changed, 271 insertions(+), 262 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/post_analysis_normalize.rs delete mode 100644 compiler/rustc_mir_transform/src/reveal_all.rs create mode 100644 tests/mir-opt/inline/issue_78442.bar.PostAnalysisNormalize.panic-abort.diff create mode 100644 tests/mir-opt/inline/issue_78442.bar.PostAnalysisNormalize.panic-unwind.diff delete mode 100644 tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff delete mode 100644 tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 7dd2139cf90..cab5b35c18d 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -80,7 +80,7 @@ pub(crate) fn get_function_sig<'tcx>( clif_sig_from_fn_abi( tcx, default_call_conv, - &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()), + &FullyMonomorphizedLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()), ) } @@ -438,9 +438,9 @@ pub(crate) fn codegen_terminator_call<'tcx>( extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.node.ty(fx.mir, fx.tcx))), ); let fn_abi = if let Some(instance) = instance { - RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args) + FullyMonomorphizedLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args) } else { - RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_sig, extra_args) + FullyMonomorphizedLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_sig, extra_args) }; let is_cold = if fn_sig.abi() == ExternAbi::RustCold { @@ -721,8 +721,8 @@ pub(crate) fn codegen_drop<'tcx>( def: ty::InstanceKind::Virtual(drop_instance.def_id(), 0), args: drop_instance.args, }; - let fn_abi = - RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty()); + let fn_abi = FullyMonomorphizedLayoutCx(fx.tcx) + .fn_abi_of_instance(virtual_drop, ty::List::empty()); let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); @@ -764,8 +764,8 @@ pub(crate) fn codegen_drop<'tcx>( def: ty::InstanceKind::Virtual(drop_instance.def_id(), 0), args: drop_instance.args, }; - let fn_abi = - RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty()); + let fn_abi = FullyMonomorphizedLayoutCx(fx.tcx) + .fn_abi_of_instance(virtual_drop, ty::List::empty()); let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); @@ -774,8 +774,8 @@ pub(crate) fn codegen_drop<'tcx>( _ => { assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _))); - let fn_abi = - RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, ty::List::empty()); + let fn_abi = FullyMonomorphizedLayoutCx(fx.tcx) + .fn_abi_of_instance(drop_instance, ty::List::empty()); let arg_value = drop_place.place_ref( fx, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 70b7d92ce15..06cc5754894 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -103,7 +103,7 @@ pub(crate) fn codegen_fn<'tcx>( let block_map: IndexVec = (0..mir.basic_blocks.len()).map(|_| bcx.create_block()).collect(); - let fn_abi = RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()); + let fn_abi = FullyMonomorphizedLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()); // Make FunctionCx let target_config = module.target_config(); diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index c663fa32965..534557fcd41 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -311,7 +311,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { - RevealAllLayoutCx(self.tcx).handle_layout_err(err, span, ty) + FullyMonomorphizedLayoutCx(self.tcx).handle_layout_err(err, span, ty) } } @@ -323,7 +323,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request) + FullyMonomorphizedLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request) } } @@ -443,9 +443,9 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } } -pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>); +pub(crate) struct FullyMonomorphizedLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>); -impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { +impl<'tcx> LayoutOfHelpers<'tcx> for FullyMonomorphizedLayoutCx<'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err { @@ -459,7 +459,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { } } -impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { +impl<'tcx> FnAbiOfHelpers<'tcx> for FullyMonomorphizedLayoutCx<'tcx> { #[inline] fn handle_fn_abi_err( &self, @@ -485,25 +485,25 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { } } -impl<'tcx> layout::HasTyCtxt<'tcx> for RevealAllLayoutCx<'tcx> { +impl<'tcx> layout::HasTyCtxt<'tcx> for FullyMonomorphizedLayoutCx<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.0 } } -impl<'tcx> rustc_abi::HasDataLayout for RevealAllLayoutCx<'tcx> { +impl<'tcx> rustc_abi::HasDataLayout for FullyMonomorphizedLayoutCx<'tcx> { fn data_layout(&self) -> &rustc_abi::TargetDataLayout { &self.0.data_layout } } -impl<'tcx> layout::HasTypingEnv<'tcx> for RevealAllLayoutCx<'tcx> { +impl<'tcx> layout::HasTypingEnv<'tcx> for FullyMonomorphizedLayoutCx<'tcx> { fn typing_env(&self) -> ty::TypingEnv<'tcx> { ty::TypingEnv::fully_monomorphized() } } -impl<'tcx> HasTargetSpec for RevealAllLayoutCx<'tcx> { +impl<'tcx> HasTargetSpec for FullyMonomorphizedLayoutCx<'tcx> { fn target_spec(&self) -> &Target { &self.0.sess.target } diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs index 714742aeaff..a2f6691cdd2 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; -use crate::{DebugContext, RevealAllLayoutCx, has_ptr_meta}; +use crate::{DebugContext, FullyMonomorphizedLayoutCx, has_ptr_meta}; #[derive(Default)] pub(crate) struct TypeDebugContext<'tcx> { @@ -85,7 +85,7 @@ impl DebugContext { type_entry.set(gimli::DW_AT_encoding, AttributeValue::Encoding(encoding)); type_entry.set( gimli::DW_AT_byte_size, - AttributeValue::Udata(RevealAllLayoutCx(tcx).layout_of(ty).size.bytes()), + AttributeValue::Udata(FullyMonomorphizedLayoutCx(tcx).layout_of(ty).size.bytes()), ); type_id @@ -159,7 +159,7 @@ impl DebugContext { return_if_type_created_in_meantime!(type_dbg, tuple_type); let name = type_names::compute_debuginfo_type_name(tcx, tuple_type, false); - let layout = RevealAllLayoutCx(tcx).layout_of(tuple_type); + let layout = FullyMonomorphizedLayoutCx(tcx).layout_of(tuple_type); let tuple_type_id = self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_structure_type); @@ -178,7 +178,9 @@ impl DebugContext { member_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(dw_ty)); member_entry.set( gimli::DW_AT_alignment, - AttributeValue::Udata(RevealAllLayoutCx(tcx).layout_of(ty).align.pref.bytes()), + AttributeValue::Udata( + FullyMonomorphizedLayoutCx(tcx).layout_of(ty).align.pref.bytes(), + ), ); member_entry.set( gimli::DW_AT_data_member_location, @@ -198,7 +200,11 @@ impl DebugContext { self.debug_type( tcx, type_dbg, - Ty::new_array(tcx, tcx.types.u8, RevealAllLayoutCx(tcx).layout_of(ty).size.bytes()), + Ty::new_array( + tcx, + tcx.types.u8, + FullyMonomorphizedLayoutCx(tcx).layout_of(ty).size.bytes(), + ), ) } } diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 6f90d17920d..c0a3ce84d52 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -42,7 +42,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, tcx, op_sp, const_value, - RevealAllLayoutCx(tcx).layout_of(ty), + FullyMonomorphizedLayoutCx(tcx).layout_of(ty), ); global_asm.push_str(&string); } diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 0df1a30fc0a..70176754f33 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -238,7 +238,7 @@ pub(crate) fn codegen_naked_asm<'tcx>( tcx, span, const_value, - RevealAllLayoutCx(tcx).layout_of(cv.ty()), + FullyMonomorphizedLayoutCx(tcx).layout_of(cv.ty()), ); CInlineAsmOperand::Const { value } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e2379f282ec..56340ff0095 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -629,8 +629,7 @@ impl<'tcx> Body<'tcx> { ) -> Option<(u128, &'a SwitchTargets)> { // There are two places here we need to evaluate a constant. let eval_mono_const = |constant: &ConstOperand<'tcx>| { - // FIXME(#132279): what is this, why are we using an empty environment with - // `RevealAll` here. + // FIXME(#132279): what is this, why are we using an empty environment here. let typing_env = ty::TypingEnv::fully_monomorphized(); let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions( tcx, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index f9aeab6210b..97e21c152ca 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1373,9 +1373,10 @@ rustc_queries! { /// Gets the ParameterEnvironment for a given item; this environment /// will be in "user-facing" mode, meaning that it is suitable for /// type-checking etc, and it does not normalize specializable - /// associated types. This is almost always what you want, - /// unless you are doing MIR optimizations, in which case you - /// might want to use `reveal_all()` method to change modes. + /// associated types. + /// + /// You should pretty much only use this if an `infcx` is available, + /// otherwise use a `TypingEnv`. query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> { desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) } feedable @@ -1471,7 +1472,7 @@ rustc_queries! { } /// Computes the layout of a type. Note that this implicitly - /// executes in "reveal all" mode, and will normalize the input type. + /// executes in `TypingMode::PostAnalysis`, and will normalize the input type. query layout_of( key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>> ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index dab3e18de33..73fd8aa5b6c 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -504,8 +504,8 @@ impl<'tcx> Instance<'tcx> { /// ``` /// /// trying to resolve `Debug::fmt` applied to `T` will yield `Ok(None)`, because we do not - /// know what code ought to run. (Note that this setting is also affected by the - /// `RevealMode` in the parameter environment.) + /// know what code ought to run. This setting is also affected by the current `TypingMode` + /// of the environment. /// /// Presuming that coherence and type-check have succeeded, if this method is invoked /// in a monomorphic context (i.e., like during codegen), then it is guaranteed to return diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index fc29b438d3a..01ad76aedc3 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -682,14 +682,14 @@ pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasTypingEnv< /// Blanket extension trait for contexts that can compute layouts of types. pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { /// Computes the layout of a type. Note that this implicitly - /// executes in "reveal all" mode, and will normalize the input type. + /// executes in `TypingMode::PostAnalysis`, and will normalize the input type. #[inline] fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult { self.spanned_layout_of(ty, DUMMY_SP) } /// Computes the layout of a type, at `span`. Note that this implicitly - /// executes in "reveal all" mode, and will normalize the input type. + /// executes in `TypingMode::PostAnalysis`, and will normalize the input type. // FIXME(eddyb) avoid passing information like this, and instead add more // `TyCtxt::at`-like APIs to be able to do e.g. `cx.at(span).layout_of(ty)`. #[inline] diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 3250a2605df..4cde2738319 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -423,8 +423,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn async_drop_glue_morphology(self, did: DefId) -> AsyncDropGlueMorphology { let ty: Ty<'tcx> = self.type_of(did).instantiate_identity(); - // Async drop glue morphology is an internal detail, so reveal_all probably - // should be fine + // Async drop glue morphology is an internal detail, so + // using `TypingMode::PostAnalysis` probably should be fine. let typing_env = ty::TypingEnv::fully_monomorphized(); if ty.needs_async_drop(self, typing_env) { AsyncDropGlueMorphology::Custom diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 06513134a29..5db08f01fdb 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -80,11 +80,11 @@ impl<'tcx> ConstToPat<'tcx> { let pat_from_kind = |kind| Box::new(Pat { span: self.span, ty, kind }); // It's not *technically* correct to be revealing opaque types here as borrowcheck has - // not run yet. However, CTFE itself uses `Reveal::All` unconditionally even during - // typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821). As a - // result we always use a revealed env when resolving the instance to evaluate. + // not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even + // during typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821). + // As a result we always use a revealed env when resolving the instance to evaluate. // - // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All` + // FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself // instead of having this logic here let typing_env = self.tcx.erase_regions(self.typing_env).with_post_analysis_normalized(self.tcx); diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 53e282e9b46..acf3eb2b62c 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -258,7 +258,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Normalization needed b/c known panics lint runs in // `mir_drops_elaborated_and_const_checked`, which happens before // optimized MIR. Only after optimizing the MIR can we guarantee - // that the `RevealAll` pass has happened and that the body's consts + // that the `PostAnalysisNormalize` pass has happened and that the body's consts // are normalized, so any call to resolve before that needs to be // manually normalized. let val = self.tcx.try_normalize_erasing_regions(self.typing_env, c.const_).ok()?; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index bfb842e4485..f0fcb44603b 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -163,7 +163,7 @@ declare_passes! { mod remove_unneeded_drops : RemoveUnneededDrops; mod remove_zsts : RemoveZsts; mod required_consts : RequiredConstsVisitor; - mod reveal_all : RevealAll; + mod post_analysis_normalize : PostAnalysisNormalize; mod sanity_check : SanityCheck; // This pass is public to allow external drivers to perform MIR cleanup pub mod simplify : @@ -604,8 +604,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'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. - &reveal_all::RevealAll, - // Calling this after reveal_all ensures that we don't deal with opaque types. + &post_analysis_normalize::PostAnalysisNormalize, + // Calling this after `PostAnalysisNormalize` ensures that we don't deal with opaque types. &add_subtyping_projections::Subtyper, &elaborate_drops::ElaborateDrops, // This will remove extraneous landing pads which are no longer diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs new file mode 100644 index 00000000000..44690500690 --- /dev/null +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -0,0 +1,74 @@ +//! Normalizes MIR in TypingMode::PostAnalysis mode, most notably revealing +//! its opaques. + +use rustc_middle::mir::visit::*; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, Ty, TyCtxt}; + +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()); + PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body); + } +} + +struct PostAnalysisNormalizeVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, +} + +impl<'tcx> MutVisitor<'tcx> for PostAnalysisNormalizeVisitor<'tcx> { + #[inline] + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + #[inline] + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + _context: PlaceContext, + _location: Location, + ) { + // Performance optimization: don't reintern if there is no `OpaqueCast` to remove. + if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) { + return; + } + // `OpaqueCast` projections are only needed if there are opaque types on which projections + // are performed. After the `PostAnalysisNormalize` pass, all opaque types are replaced with their + // hidden types, so we don't need these projections anymore. + place.projection = self.tcx.mk_place_elems( + &place + .projection + .into_iter() + .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) + .collect::>(), + ); + self.super_place(place, _context, _location); + } + + #[inline] + fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) { + // We have to use `try_normalize_erasing_regions` here, since it's + // possible that we visit impossible-to-satisfy where clauses here, + // see #91745 + if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.typing_env, constant.const_) { + constant.const_ = c; + } + self.super_const_operand(constant, location); + } + + #[inline] + fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { + // We have to use `try_normalize_erasing_regions` here, since it's + // possible that we visit impossible-to-satisfy where clauses here, + // see #91745 + if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.typing_env, *ty) { + *ty = t; + } + } +} diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index ad62b47a66d..a535be798cd 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -2,7 +2,8 @@ //! //! When the MIR is built, we check `needs_drop` before emitting a `Drop` for a place. This pass is //! useful because (unlike MIR building) it runs after type checking, so it can make use of -//! `Reveal::All` to provide more precise type information. +//! `TypingMode::PostAnalysis` to provide more precise type information, especially about opaque +//! types. use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs deleted file mode 100644 index 587032ee720..00000000000 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! Normalizes MIR in RevealAll mode. - -use rustc_middle::mir::visit::*; -use rustc_middle::mir::*; -use rustc_middle::ty::{self, Ty, TyCtxt}; - -pub(super) struct RevealAll; - -impl<'tcx> crate::MirPass<'tcx> for RevealAll { - 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()); - RevealAllVisitor { tcx, typing_env }.visit_body_preserves_cfg(body); - } -} - -struct RevealAllVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - typing_env: ty::TypingEnv<'tcx>, -} - -impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { - #[inline] - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - #[inline] - fn visit_place( - &mut self, - place: &mut Place<'tcx>, - _context: PlaceContext, - _location: Location, - ) { - // Performance optimization: don't reintern if there is no `OpaqueCast` to remove. - if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) { - return; - } - // `OpaqueCast` projections are only needed if there are opaque types on which projections - // are performed. After the `RevealAll` pass, all opaque types are replaced with their - // hidden types, so we don't need these projections anymore. - place.projection = self.tcx.mk_place_elems( - &place - .projection - .into_iter() - .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) - .collect::>(), - ); - self.super_place(place, _context, _location); - } - - #[inline] - fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) { - // We have to use `try_normalize_erasing_regions` here, since it's - // possible that we visit impossible-to-satisfy where clauses here, - // see #91745 - if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.typing_env, constant.const_) { - constant.const_ = c; - } - self.super_const_operand(constant, location); - } - - #[inline] - fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { - // We have to use `try_normalize_erasing_regions` here, since it's - // possible that we visit impossible-to-satisfy where clauses here, - // see #91745 - if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.typing_env, *ty) { - *ty = t; - } - } -} diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f16cde7cd4e..809357ec110 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -141,7 +141,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< debug!("make_shim({:?}) = untransformed {:?}", instance, result); // We don't validate MIR here because the shims may generate code that's - // only valid in a reveal-all param-env. However, since we do initial + // only valid in a `PostAnalysis` param-env. However, since we do initial // validation with the MirBuilt phase, which uses a user-facing param-env. // This causes validation errors when TAITs are involved. pm::run_passes_no_validate( diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 1739fdcc9af..51e5c49cea1 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -646,7 +646,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { { self.fail( location, - format!("explicit opaque type cast to `{ty}` after `RevealAll`"), + format!("explicit opaque type cast to `{ty}` after `PostAnalysisNormalize`"), ) } ProjectionElem::Index(index) => { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 8ee9ac3df72..5efe7ffc7b9 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1556,7 +1556,7 @@ fn create_mono_items_for_default_impls<'tcx>( // Unlike 'lazy' monomorphization that begins by collecting items transitively // called by `main` or other global items, when eagerly monomorphizing impl // items, we never actually check that the predicates of this impl are satisfied - // in a empty reveal-all param env (i.e. with no assumptions). + // in a empty param env (i.e. with no assumptions). // // Even though this impl has no type or const generic parameters, because we don't // consider higher-ranked predicates such as `for<'a> &'a mut [u8]: Copy` to diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 19d17a358ed..336bcb9df33 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -1,6 +1,5 @@ //! Computes a normalizes-to (projection) goal for opaque types. This goal -//! behaves differently depending on the param-env's reveal mode and whether -//! the opaque is in a defining scope. +//! behaves differently depending on the current `TypingMode`. use rustc_index::bit_set::GrowableBitSet; use rustc_type_ir::inherent::*; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 0e89a0c6545..7d6c38c11f3 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -603,12 +603,12 @@ pub fn try_evaluate_const<'tcx>( }; let uv = ty::UnevaluatedConst::new(uv.def, args); - // It's not *technically* correct to be revealing opaque types here as we could still be - // before borrowchecking. However, CTFE itself uses `Reveal::All` unconditionally even during - // typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821). As a result we - // always use a revealed env when resolving the instance to evaluate. + // It's not *technically* correct to be revealing opaque types here as borrowcheck has + // not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even + // during typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821). + // As a result we always use a revealed env when resolving the instance to evaluate. // - // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All` + // FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself // instead of having this logic here let typing_env = tcx.erase_regions(infcx.typing_env(param_env)).with_post_analysis_normalized(tcx); diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 0a2ba2b4b20..4d3d8c66e62 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -115,7 +115,7 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( ) -> bool { let mut flags = ty::TypeFlags::HAS_ALIAS; - // Opaques are treated as rigid with `Reveal::UserFacing`, + // Opaques are treated as rigid outside of `TypingMode::PostAnalysis`, // so we can ignore those. match infcx.typing_mode() { TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 98c31f5ce0f..8798772e398 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -133,8 +133,10 @@ fn resolve_associated_item<'tcx>( bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id); }); - // Since this is a trait item, we need to see if the item is either a trait default item - // or a specialization because we can't resolve those unless we can `Reveal::All`. + // Since this is a trait item, we need to see if the item is either a trait + // default item or a specialization because we can't resolve those until we're + // in `TypingMode::PostAnalysis`. + // // NOTE: This should be kept in sync with the similar code in // `rustc_trait_selection::traits::project::assemble_candidates_from_impls()`. let eligible = if leaf_def.is_final() { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 2fcdf6433fa..66134b81b2a 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -46,9 +46,9 @@ fn layout_of<'tcx>( let PseudoCanonicalInput { typing_env, value: ty } = query; debug!(?ty); - // Optimization: We convert to RevealAll and convert opaque types in the where bounds - // to their hidden types. This reduces overall uncached invocations of `layout_of` and - // is thus a small performance improvement. + // Optimization: We convert to TypingMode::PostAnalysis and convert opaque types in + // the where bounds to their hidden types. This reduces overall uncached invocations + // of `layout_of` and is thus a small performance improvement. let typing_env = typing_env.with_post_analysis_normalized(tcx); let unnormalized_ty = ty; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 5e3a3df0038..4213ef4803b 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -444,7 +444,7 @@ pub enum AliasTermKind { /// An associated type in an inherent `impl` InherentTy, /// An opaque type (usually from `impl Trait` in type aliases or function return types) - /// Can only be normalized away in RevealAll mode + /// Can only be normalized away in PostAnalysis mode or its defining scope. OpaqueTy, /// A type alias that actually checks its trait bounds. /// Currently only used if the type alias references opaque types. diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 499e6d3dd37..033fcdb6c03 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -41,7 +41,7 @@ pub enum AliasTyKind { /// An associated type in an inherent `impl` Inherent, /// An opaque type (usually from `impl Trait` in type aliases or function return types) - /// Can only be normalized away in RevealAll mode + /// Can only be normalized away in PostAnalysis mode or its defining scope. Opaque, /// A type alias that actually checks its trait bounds. /// Currently only used if the type alias references opaque types. diff --git a/tests/mir-opt/inline/issue_78442.bar.PostAnalysisNormalize.panic-abort.diff b/tests/mir-opt/inline/issue_78442.bar.PostAnalysisNormalize.panic-abort.diff new file mode 100644 index 00000000000..95c52925401 --- /dev/null +++ b/tests/mir-opt/inline/issue_78442.bar.PostAnalysisNormalize.panic-abort.diff @@ -0,0 +1,58 @@ +- // MIR for `bar` before PostAnalysisNormalize ++ // MIR for `bar` after PostAnalysisNormalize + + fn bar(_1: P) -> () { + debug _baz => _1; + let mut _0: (); + let _2: (); +- let mut _3: &impl Fn(); +- let _4: impl Fn(); ++ let mut _3: &fn() {foo}; ++ let _4: fn() {foo}; + let mut _5: (); + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _4 = hide_foo() -> [return: bb1, unwind: bb6]; + } + + bb1: { + _3 = &_4; + StorageLive(_5); + _5 = (); +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; ++ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; + } + + bb2: { + StorageDead(_5); + StorageDead(_3); + drop(_4) -> [return: bb3, unwind: bb6]; + } + + bb3: { + StorageDead(_4); + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb4, unwind: bb7]; + } + + bb4: { + return; + } + + bb5 (cleanup): { + drop(_4) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { + drop(_1) -> [return: bb7, unwind terminate(cleanup)]; + } + + bb7 (cleanup): { + resume; + } + } + diff --git a/tests/mir-opt/inline/issue_78442.bar.PostAnalysisNormalize.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.PostAnalysisNormalize.panic-unwind.diff new file mode 100644 index 00000000000..1b710a78cb1 --- /dev/null +++ b/tests/mir-opt/inline/issue_78442.bar.PostAnalysisNormalize.panic-unwind.diff @@ -0,0 +1,58 @@ +- // MIR for `bar` before PostAnalysisNormalize ++ // MIR for `bar` after PostAnalysisNormalize + + fn bar(_1: P) -> () { + debug _baz => _1; + let mut _0: (); + let _2: (); +- let mut _3: &impl Fn(); +- let _4: impl Fn(); ++ let mut _3: &fn() {foo}; ++ let _4: fn() {foo}; + let mut _5: (); + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _4 = hide_foo() -> [return: bb1, unwind: bb6]; + } + + bb1: { + _3 = &_4; + StorageLive(_5); + _5 = (); +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; ++ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; + } + + bb2: { + StorageDead(_5); + StorageDead(_3); + drop(_4) -> [return: bb3, unwind: bb6]; + } + + bb3: { + StorageDead(_4); + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb4, unwind continue]; + } + + bb4: { + return; + } + + bb5 (cleanup): { + drop(_4) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { + drop(_1) -> [return: bb7, unwind terminate(cleanup)]; + } + + bb7 (cleanup): { + resume; + } + } + diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff deleted file mode 100644 index b532b133a83..00000000000 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff +++ /dev/null @@ -1,58 +0,0 @@ -- // MIR for `bar` before RevealAll -+ // MIR for `bar` after RevealAll - - fn bar(_1: P) -> () { - debug _baz => _1; - let mut _0: (); - let _2: (); -- let mut _3: &impl Fn(); -- let _4: impl Fn(); -+ let mut _3: &fn() {foo}; -+ let _4: fn() {foo}; - let mut _5: (); - - bb0: { - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind: bb6]; - } - - bb1: { - _3 = &_4; - StorageLive(_5); - _5 = (); -- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; -+ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; - } - - bb2: { - StorageDead(_5); - StorageDead(_3); - drop(_4) -> [return: bb3, unwind: bb6]; - } - - bb3: { - StorageDead(_4); - StorageDead(_2); - _0 = const (); - drop(_1) -> [return: bb4, unwind: bb7]; - } - - bb4: { - return; - } - - bb5 (cleanup): { - drop(_4) -> [return: bb6, unwind terminate(cleanup)]; - } - - bb6 (cleanup): { - drop(_1) -> [return: bb7, unwind terminate(cleanup)]; - } - - bb7 (cleanup): { - resume; - } - } - diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff deleted file mode 100644 index bcebcf297c2..00000000000 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff +++ /dev/null @@ -1,58 +0,0 @@ -- // MIR for `bar` before RevealAll -+ // MIR for `bar` after RevealAll - - fn bar(_1: P) -> () { - debug _baz => _1; - let mut _0: (); - let _2: (); -- let mut _3: &impl Fn(); -- let _4: impl Fn(); -+ let mut _3: &fn() {foo}; -+ let _4: fn() {foo}; - let mut _5: (); - - bb0: { - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind: bb6]; - } - - bb1: { - _3 = &_4; - StorageLive(_5); - _5 = (); -- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; -+ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; - } - - bb2: { - StorageDead(_5); - StorageDead(_3); - drop(_4) -> [return: bb3, unwind: bb6]; - } - - bb3: { - StorageDead(_4); - StorageDead(_2); - _0 = const (); - drop(_1) -> [return: bb4, unwind continue]; - } - - bb4: { - return; - } - - bb5 (cleanup): { - drop(_4) -> [return: bb6, unwind terminate(cleanup)]; - } - - bb6 (cleanup): { - drop(_1) -> [return: bb7, unwind terminate(cleanup)]; - } - - bb7 (cleanup): { - resume; - } - } - diff --git a/tests/mir-opt/inline/issue_78442.rs b/tests/mir-opt/inline/issue_78442.rs index 6dc875f9a40..4eb5c142034 100644 --- a/tests/mir-opt/inline/issue_78442.rs +++ b/tests/mir-opt/inline/issue_78442.rs @@ -2,7 +2,7 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] -// EMIT_MIR issue_78442.bar.RevealAll.diff +// EMIT_MIR issue_78442.bar.PostAnalysisNormalize.diff // EMIT_MIR issue_78442.bar.Inline.diff pub fn bar

( // Error won't happen if "bar" is not generic diff --git a/tests/ui/impl-trait/transmute/in-defining-scope.rs b/tests/ui/impl-trait/transmute/in-defining-scope.rs index b9a9dbc10a5..4c8e1852a91 100644 --- a/tests/ui/impl-trait/transmute/in-defining-scope.rs +++ b/tests/ui/impl-trait/transmute/in-defining-scope.rs @@ -1,5 +1,5 @@ -// This causes a query cycle due to using `Reveal::All`, -// in #119821 const eval was changed to always use `Reveal::All` +// This causes a query cycle due to using `TypingEnv::PostAnalysis`, +// in #119821 const eval was changed to always use this mode. // // See that PR for more details. use std::mem::transmute; diff --git a/tests/ui/mir/validate/needs-reveal-all.rs b/tests/ui/mir/validate/needs-reveal-all.rs index be2f5dd322f..7d793ebbba6 100644 --- a/tests/ui/mir/validate/needs-reveal-all.rs +++ b/tests/ui/mir/validate/needs-reveal-all.rs @@ -1,8 +1,8 @@ -// Regression test for #105009. the issue here was that even after the `RevealAll` pass, +// Regression test for #105009. the issue here was that even after the `PostAnalysisNormalize` pass, // `validate` still used `Reveal::UserFacing`. This meant that it now ends up comparing // opaque types with their revealed version, resulting in an ICE. // -// We're using these flags to run the `RevealAll` pass while making it less likely to +// We're using these flags to run the `PostAnalysisNormalize` pass while making it less likely to // accidentally removing the assignment from `Foo` to `Foo`. //@ compile-flags: -Zinline_mir=yes -Zmir-opt-level=0 -Zvalidate-mir diff --git a/tests/ui/sanitizer/cfi/can-reveal-opaques.rs b/tests/ui/sanitizer/cfi/can-reveal-opaques.rs index 55988a62a8c..99c12d72eb5 100644 --- a/tests/ui/sanitizer/cfi/can-reveal-opaques.rs +++ b/tests/ui/sanitizer/cfi/can-reveal-opaques.rs @@ -39,6 +39,6 @@ fn main() { // So why is the second generic of `test` "`()`", and not the // `impl Sized` since we inferred it from the return type of `rpit_fn` // during typeck? Well, that's because we're using the generics from the - // terminator of the MIR, which has had the RevealAll pass performed on it. + // terminator of the MIR, which has had the PostAnalysisNormalize pass performed on it. let _ = test(rpit_fn); } diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.rs b/tests/ui/type-alias-impl-trait/in-where-clause.rs index a089fdc9075..065af57a864 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.rs +++ b/tests/ui/type-alias-impl-trait/in-where-clause.rs @@ -1,4 +1,4 @@ -//! We evaluate `1 + 2` with `Reveal::All` during typeck, causing +//! We evaluate `1 + 2` with `TypingMode::PostAnalysis` during typeck, causing //! us to get the concrete type of `Bar` while computing it. //! This again requires type checking `foo`. #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs b/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs index 9901c8fe25d..c52dbd32539 100644 --- a/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs +++ b/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Zvalidate-mir //@ check-pass -// Check that we don't cause cycle errors when validating pre-`Reveal::All` MIR +// Check that we don't cause cycle errors when validating pre-`RevealOpaques` MIR // that assigns opaques through normalized projections. #![feature(impl_trait_in_assoc_type)] -- cgit 1.4.1-3-g733a5 From 8c7c83d6ef33864426ae607af24399b2687ad979 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 22 Nov 2024 12:01:16 +0100 Subject: review --- compiler/rustc_middle/src/query/mod.rs | 5 ++-- .../src/post_analysis_normalize.rs | 5 ++-- compiler/rustc_type_ir/src/infer_ctxt.rs | 31 +++++++++++++++++++++- 3 files changed, 36 insertions(+), 5 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 97e21c152ca..e94e0332aa4 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1375,8 +1375,9 @@ rustc_queries! { /// type-checking etc, and it does not normalize specializable /// associated types. /// - /// You should pretty much only use this if an `infcx` is available, - /// otherwise use a `TypingEnv`. + /// You should almost certainly not use this. If you already have an InferCtxt, then + /// you should also probably have a `ParamEnv` from when it was built. If you don't, + /// then you should take a `TypingEnv` to ensure that you handle opaque types correctly. query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> { desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) } feedable diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs index 44690500690..c842e92b527 100644 --- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -1,5 +1,6 @@ -//! Normalizes MIR in TypingMode::PostAnalysis mode, most notably revealing -//! its opaques. +//! Normalizes MIR in `TypingMode::PostAnalysis`` mode, most notably revealing +//! its opaques. We also only normalize specializable associated items once in +//! `PostAnalysis` mode. use rustc_middle::mir::visit::*; use rustc_middle::mir::*; diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index c2b43416623..13ad505bc04 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -39,9 +39,38 @@ pub enum TypingMode { /// /// We only normalize opaque types which may get defined by the current body, /// which are stored in `defining_opaque_types`. + /// + /// We also refuse to project any associated type that is marked `default`. + /// Non-`default` ("final") types are always projected. This is necessary in + /// general for soundness of specialization. However, we *could* allow projections + /// in fully-monomorphic cases. We choose not to, because we prefer for `default type` + /// to force the type definition to be treated abstractly by any consumers of the + /// impl. Concretely, that means that the following example will + /// fail to compile: + /// + /// ```compile_fail,E0308 + /// #![feature(specialization)] + /// trait Assoc { + /// type Output; + /// } + /// + /// impl Assoc for T { + /// default type Output = bool; + /// } + /// + /// fn main() { + /// let x: <() as Assoc>::Output = true; + /// } + /// ``` Analysis { defining_opaque_types: I::DefiningOpaqueTypes }, /// After analysis, mostly during codegen and MIR optimizations, we're able to - /// reveal all opaque types. + /// reveal all opaque types. As the concrete type should *never* be observable + /// directly by the user, this should not be used by checks which may expose + /// such details to the user. + /// + /// There are some exceptions to this as for example `layout_of` and const-evaluation + /// always run in `PostAnalysis` mode, even when used during analysis. This exposes + /// some information about the underlying type to users, but not the type itself. PostAnalysis, } -- cgit 1.4.1-3-g733a5 From 776731dc3f5396cb8f2f9b94a667f3926d8f5765 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 22 Nov 2024 12:13:29 +0100 Subject: rebase --- compiler/rustc_middle/src/query/mod.rs | 2 +- .../src/lint_tail_expr_drop_order.rs | 31 +++++++++------------- .../src/post_analysis_normalize.rs | 2 +- compiler/rustc_ty_utils/src/needs_drop.rs | 6 ++--- 4 files changed, 18 insertions(+), 23 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e94e0332aa4..0f2a6d598a0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1467,7 +1467,7 @@ rustc_queries! { /// *IMPORTANT*: *DO NOT* run this query before promoted MIR body is constructed, /// because this query partially depends on that query. /// Otherwise, there is a risk of query cycles. - query list_significant_drop_tys(ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> &'tcx ty::List> { + query list_significant_drop_tys(ty: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> &'tcx ty::List> { desc { |tcx| "computing when `{}` has a significant destructor", ty.value } cache_on_disk_if { false } } diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index b8502fcbafb..732a9cd9890 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -216,22 +216,17 @@ fn true_significant_drop_ty<'tcx>( /// Returns the list of types with a "potentially sigificant" that may be dropped /// by dropping a value of type `ty`. -#[instrument(level = "debug", skip(tcx, param_env))] +#[instrument(level = "debug", skip(tcx, typing_env))] fn extract_component_raw<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ty_seen: &mut UnordSet>, ) -> SmallVec<[Ty<'tcx>; 4]> { // Droppiness does not depend on regions, so let us erase them. - let ty = tcx - .try_normalize_erasing_regions( - ty::TypingEnv { param_env, typing_mode: ty::TypingMode::PostAnalysis }, - ty, - ) - .unwrap_or(ty); - - let tys = tcx.list_significant_drop_tys(param_env.and(ty)); + let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); + + let tys = tcx.list_significant_drop_tys(typing_env.as_query_input(ty)); debug!(?ty, "components"); let mut out_tys = smallvec![]; for ty in tys { @@ -239,7 +234,7 @@ fn extract_component_raw<'tcx>( // Some types can be further opened up because the drop is simply delegated for ty in tys { if ty_seen.insert(ty) { - out_tys.extend(extract_component_raw(tcx, param_env, ty, ty_seen)); + out_tys.extend(extract_component_raw(tcx, typing_env, ty, ty_seen)); } } } else { @@ -251,13 +246,13 @@ fn extract_component_raw<'tcx>( out_tys } -#[instrument(level = "debug", skip(tcx, param_env))] +#[instrument(level = "debug", skip(tcx, typing_env))] fn extract_component_with_significant_dtor<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ) -> SmallVec<[Ty<'tcx>; 4]> { - let mut tys = extract_component_raw(tcx, param_env, ty, &mut Default::default()); + let mut tys = extract_component_raw(tcx, typing_env, ty, &mut Default::default()); let mut deduplicate = FxHashSet::default(); tys.retain(|oty| deduplicate.insert(*oty)); tys.into_iter().collect() @@ -359,7 +354,7 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body< // We group them per-block because they tend to scheduled in the same drop ladder block. let mut bid_per_block = IndexMap::default(); let mut bid_places = UnordSet::new(); - let param_env = tcx.param_env(def_id).with_reveal_all_normalized(tcx); + let typing_env = ty::TypingEnv::post_analysis(tcx, def_id); let mut ty_dropped_components = UnordMap::default(); for (block, data) in body.basic_blocks.iter_enumerated() { for (statement_index, stmt) in data.statements.iter().enumerate() { @@ -367,7 +362,7 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body< let ty = place.ty(body, tcx).ty; if ty_dropped_components .entry(ty) - .or_insert_with(|| extract_component_with_significant_dtor(tcx, param_env, ty)) + .or_insert_with(|| extract_component_with_significant_dtor(tcx, typing_env, ty)) .is_empty() { continue; @@ -479,7 +474,7 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body< if ty_dropped_components .entry(observer_ty) .or_insert_with(|| { - extract_component_with_significant_dtor(tcx, param_env, observer_ty) + extract_component_with_significant_dtor(tcx, typing_env, observer_ty) }) .is_empty() { @@ -575,7 +570,7 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body< let name = name.as_str(); let mut seen_dyn = false; - let destructors = extract_component_with_significant_dtor(tcx, param_env, observer_ty) + let destructors = extract_component_with_significant_dtor(tcx, typing_env, observer_ty) .into_iter() .filter_map(|ty| { if let Some(span) = ty_dtor_span(tcx, ty) { diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs index c842e92b527..3eecf79a7ea 100644 --- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -1,4 +1,4 @@ -//! Normalizes MIR in `TypingMode::PostAnalysis`` mode, most notably revealing +//! Normalizes MIR in `TypingMode::PostAnalysis` mode, most notably revealing //! its opaques. We also only normalize specializable associated items once in //! `PostAnalysis` mode. diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 469a4ac3e41..d85da7d355e 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -431,13 +431,13 @@ fn adt_significant_drop_tys( #[instrument(level = "debug", skip(tcx), ret)] fn list_significant_drop_tys<'tcx>( tcx: TyCtxt<'tcx>, - ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> &'tcx ty::List> { tcx.mk_type_list( &drop_tys_helper( tcx, - ty.value, - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: ty.param_env }, + key.value, + key.typing_env, adt_consider_insignificant_dtor(tcx), true, true, -- cgit 1.4.1-3-g733a5 From b9fb1a69d2fe1c146cbdf181cf9e0eaf15935799 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 24 Nov 2024 18:50:08 +1100 Subject: coverage: Store coverage source regions as `Span` until codegen --- .../rustc_codegen_llvm/src/coverageinfo/ffi.rs | 28 +--- .../src/coverageinfo/map_data.rs | 14 +- .../rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 26 +++- .../src/coverageinfo/mapgen/spans.rs | 124 +++++++++++++++ compiler/rustc_codegen_llvm/src/lib.rs | 1 + compiler/rustc_middle/src/mir/coverage.rs | 18 +-- compiler/rustc_middle/src/mir/pretty.rs | 4 +- compiler/rustc_mir_transform/src/coverage/mod.rs | 166 +++------------------ .../branch_match_arms.main.InstrumentCoverage.diff | 12 +- ...instrument_coverage.bar.InstrumentCoverage.diff | 2 +- ...nstrument_coverage.main.InstrumentCoverage.diff | 10 +- ..._coverage_cleanup.main.CleanupPostBorrowck.diff | 10 +- ...t_coverage_cleanup.main.InstrumentCoverage.diff | 10 +- 13 files changed, 199 insertions(+), 226 deletions(-) create mode 100644 compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 7aa03908f0f..19d6726002c 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,6 +1,4 @@ -use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId, SourceRegion}; - -use crate::coverageinfo::mapgen::LocalFileId; +use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId}; /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] @@ -126,30 +124,16 @@ pub(crate) struct CoverageSpan { /// Local index into the function's local-to-global file ID table. /// The value at that index is itself an index into the coverage filename /// table in the CGU's `__llvm_covmap` section. - file_id: u32, + pub(crate) file_id: u32, /// 1-based starting line of the source code span. - start_line: u32, + pub(crate) start_line: u32, /// 1-based starting column of the source code span. - start_col: u32, + pub(crate) start_col: u32, /// 1-based ending line of the source code span. - end_line: u32, + pub(crate) end_line: u32, /// 1-based ending column of the source code span. High bit must be unset. - end_col: u32, -} - -impl CoverageSpan { - pub(crate) fn from_source_region( - local_file_id: LocalFileId, - code_region: &SourceRegion, - ) -> Self { - let file_id = local_file_id.as_u32(); - let &SourceRegion { start_line, start_col, end_line, end_col } = code_region; - // Internally, LLVM uses the high bit of `end_col` to distinguish between - // code regions and gap regions, so it can't be used by the column number. - assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}"); - Self { file_id, start_line, start_col, end_line, end_col } - } + pub(crate) end_col: u32, } /// Must match the layout of `LLVMRustCoverageCodeRegion`. diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index e3c0df27883..95746b88ced 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -3,9 +3,9 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::BitSet; use rustc_middle::mir::coverage::{ CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, MappingKind, Op, - SourceRegion, }; use rustc_middle::ty::Instance; +use rustc_span::Span; use tracing::{debug, instrument}; use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; @@ -220,16 +220,16 @@ impl<'tcx> FunctionCoverage<'tcx> { }) } - /// Converts this function's coverage mappings into an intermediate form - /// that will be used by `mapgen` when preparing for FFI. - pub(crate) fn counter_regions( + /// Yields all this function's coverage mappings, after simplifying away + /// unused counters and counter expressions. + pub(crate) fn mapping_spans( &self, - ) -> impl Iterator + ExactSizeIterator { + ) -> impl Iterator + ExactSizeIterator + Captures<'_> { self.function_coverage_info.mappings.iter().map(move |mapping| { - let Mapping { kind, source_region } = mapping; + let &Mapping { ref kind, span } = mapping; let kind = kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term }); - (kind, source_region) + (kind, span) }) } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 0c79cd5c262..e8dfed1f06a 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,3 +1,5 @@ +mod spans; + use std::ffi::CString; use std::iter; @@ -201,7 +203,7 @@ rustc_index::newtype_index! { /// An index into a function's list of global file IDs. That underlying list /// of local-to-global mappings will be embedded in the function's record in /// the `__llvm_covfun` linker section. - pub(crate) struct LocalFileId {} + struct LocalFileId {} } /// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU) @@ -244,11 +246,13 @@ fn encode_mappings_for_function( global_file_table: &GlobalFileTable, function_coverage: &FunctionCoverage<'_>, ) -> Vec { - let counter_regions = function_coverage.counter_regions(); - if counter_regions.is_empty() { + let mapping_spans = function_coverage.mapping_spans(); + if mapping_spans.is_empty() { return Vec::new(); } + let fn_cov_info = function_coverage.function_coverage_info; + let expressions = function_coverage.counter_expressions().collect::>(); let mut virtual_file_mapping = VirtualFileMapping::default(); @@ -258,7 +262,9 @@ fn encode_mappings_for_function( let mut mcdc_decision_regions = vec![]; // Currently a function's mappings must all be in the same file as its body span. - let file_name = span_file_name(tcx, function_coverage.function_coverage_info.body_span); + let file_name = span_file_name(tcx, fn_cov_info.body_span); + let source_map = tcx.sess.source_map(); + let source_file = source_map.lookup_source_file(fn_cov_info.body_span.lo()); // Look up the global file ID for that filename. let global_file_id = global_file_table.global_file_id_for_file_name(file_name); @@ -267,11 +273,15 @@ fn encode_mappings_for_function( let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id); debug!(" file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'"); - // For each counter/region pair in this function+file, convert it to a + let make_cov_span = |span| { + spans::make_coverage_span(local_file_id, source_map, fn_cov_info, &source_file, span) + }; + + // For each coverage mapping span in this function+file, convert it to a // form suitable for FFI. - for (mapping_kind, region) in counter_regions { - debug!("Adding counter {mapping_kind:?} to map for {region:?}"); - let cov_span = ffi::CoverageSpan::from_source_region(local_file_id, region); + for (mapping_kind, span) in mapping_spans { + debug!("Adding counter {mapping_kind:?} to map for {span:?}"); + let Some(cov_span) = make_cov_span(span) else { continue }; match mapping_kind { MappingKind::Code(term) => { code_regions diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs new file mode 100644 index 00000000000..4a7721879fd --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs @@ -0,0 +1,124 @@ +use rustc_middle::mir::coverage::FunctionCoverageInfo; +use rustc_span::source_map::SourceMap; +use rustc_span::{BytePos, Pos, SourceFile, Span}; +use tracing::debug; + +use crate::coverageinfo::ffi; +use crate::coverageinfo::mapgen::LocalFileId; + +/// Converts the span into its start line and column, and end line and column. +/// +/// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by +/// the compiler, these column numbers are denoted in **bytes**, because that's what +/// LLVM's `llvm-cov` tool expects to see in coverage maps. +/// +/// Returns `None` if the conversion failed for some reason. This shouldn't happen, +/// but it's hard to rule out entirely (especially in the presence of complex macros +/// or other expansions), and if it does happen then skipping a span or function is +/// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. +pub(crate) fn make_coverage_span( + file_id: LocalFileId, + source_map: &SourceMap, + fn_cov_info: &FunctionCoverageInfo, + file: &SourceFile, + span: Span, +) -> Option { + let span = ensure_non_empty_span(source_map, fn_cov_info, span)?; + + let lo = span.lo(); + let hi = span.hi(); + + // Column numbers need to be in bytes, so we can't use the more convenient + // `SourceMap` methods for looking up file coordinates. + let line_and_byte_column = |pos: BytePos| -> Option<(usize, usize)> { + let rpos = file.relative_position(pos); + let line_index = file.lookup_line(rpos)?; + let line_start = file.lines()[line_index]; + // Line numbers and column numbers are 1-based, so add 1 to each. + Some((line_index + 1, (rpos - line_start).to_usize() + 1)) + }; + + let (mut start_line, start_col) = line_and_byte_column(lo)?; + let (mut end_line, end_col) = line_and_byte_column(hi)?; + + // Apply an offset so that code in doctests has correct line numbers. + // FIXME(#79417): Currently we have no way to offset doctest _columns_. + start_line = source_map.doctest_offset_line(&file.name, start_line); + end_line = source_map.doctest_offset_line(&file.name, end_line); + + check_coverage_span(ffi::CoverageSpan { + file_id: file_id.as_u32(), + start_line: start_line as u32, + start_col: start_col as u32, + end_line: end_line as u32, + end_col: end_col as u32, + }) +} + +fn ensure_non_empty_span( + source_map: &SourceMap, + fn_cov_info: &FunctionCoverageInfo, + span: Span, +) -> Option { + if !span.is_empty() { + return Some(span); + } + + let lo = span.lo(); + let hi = span.hi(); + + // The span is empty, so try to expand it to cover an adjacent '{' or '}', + // but only within the bounds of the body span. + let try_next = hi < fn_cov_info.body_span.hi(); + let try_prev = fn_cov_info.body_span.lo() < lo; + if !(try_next || try_prev) { + return None; + } + + source_map + .span_to_source(span, |src, start, end| try { + // We're only checking for specific ASCII characters, so we don't + // have to worry about multi-byte code points. + if try_next && src.as_bytes()[end] == b'{' { + Some(span.with_hi(hi + BytePos(1))) + } else if try_prev && src.as_bytes()[start - 1] == b'}' { + Some(span.with_lo(lo - BytePos(1))) + } else { + None + } + }) + .ok()? +} + +/// If `llvm-cov` sees a source region that is improperly ordered (end < start), +/// it will immediately exit with a fatal error. To prevent that from happening, +/// discard regions that are improperly ordered, or might be interpreted in a +/// way that makes them improperly ordered. +fn check_coverage_span(cov_span: ffi::CoverageSpan) -> Option { + let ffi::CoverageSpan { file_id: _, start_line, start_col, end_line, end_col } = cov_span; + + // Line/column coordinates are supposed to be 1-based. If we ever emit + // coordinates of 0, `llvm-cov` might misinterpret them. + let all_nonzero = [start_line, start_col, end_line, end_col].into_iter().all(|x| x != 0); + // Coverage mappings use the high bit of `end_col` to indicate that a + // region is actually a "gap" region, so make sure it's unset. + let end_col_has_high_bit_unset = (end_col & (1 << 31)) == 0; + // If a region is improperly ordered (end < start), `llvm-cov` will exit + // with a fatal error, which is inconvenient for users and hard to debug. + let is_ordered = (start_line, start_col) <= (end_line, end_col); + + if all_nonzero && end_col_has_high_bit_unset && is_ordered { + Some(cov_span) + } else { + debug!( + ?cov_span, + ?all_nonzero, + ?end_col_has_high_bit_unset, + ?is_ordered, + "Skipping source region that would be misinterpreted or rejected by LLVM" + ); + // If this happens in a debug build, ICE to make it easier to notice. + debug_assert!(false, "Improper source region: {cov_span:?}"); + None + } +} diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 3dfb86d422d..9f398107fc6 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -17,6 +17,7 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![feature(try_blocks)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 11a4e7f89a7..33f9a2bdca6 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -155,22 +155,6 @@ impl Debug for CoverageKind { } } -#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct SourceRegion { - pub start_line: u32, - pub start_col: u32, - pub end_line: u32, - pub end_col: u32, -} - -impl Debug for SourceRegion { - fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - let &Self { start_line, start_col, end_line, end_col } = self; - write!(fmt, "{start_line}:{start_col} - {end_line}:{end_col}") - } -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] #[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub enum Op { @@ -232,7 +216,7 @@ impl MappingKind { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Mapping { pub kind: MappingKind, - pub source_region: SourceRegion, + pub span: Span, } /// Stores per-function coverage information attached to a `mir::Body`, diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 2bfcd0a6227..ece468947c2 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -603,8 +603,8 @@ fn write_function_coverage_info( for (id, expression) in expressions.iter_enumerated() { writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; } - for coverage::Mapping { kind, source_region } in mappings { - writeln!(w, "{INDENT}coverage {kind:?} => {source_region:?};")?; + for coverage::Mapping { kind, span } in mappings { + writeln!(w, "{INDENT}coverage {kind:?} => {span:?};")?; } writeln!(w)?; diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index e8b3d80be02..02fd289b6ef 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -13,16 +13,15 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::mir::coverage::{ - CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, SourceRegion, + CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, }; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::TyCtxt; +use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, Pos, SourceFile, Span}; use tracing::{debug, debug_span, trace}; use crate::coverage::counters::{CounterIncrementSite, CoverageCounters}; @@ -97,7 +96,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: let coverage_counters = CoverageCounters::make_bcb_counters(&basic_coverage_blocks, &bcbs_with_counter_mappings); - let mappings = create_mappings(tcx, &hir_info, &extracted_mappings, &coverage_counters); + let mappings = create_mappings(&extracted_mappings, &coverage_counters); if mappings.is_empty() { // No spans could be converted into valid mappings, so skip this function. debug!("no spans could be converted into valid mappings; skipping"); @@ -136,18 +135,12 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: /// /// Precondition: All BCBs corresponding to those spans have been given /// coverage counters. -fn create_mappings<'tcx>( - tcx: TyCtxt<'tcx>, - hir_info: &ExtractedHirInfo, +fn create_mappings( extracted_mappings: &ExtractedMappings, coverage_counters: &CoverageCounters, ) -> Vec { - let source_map = tcx.sess.source_map(); - let file = source_map.lookup_source_file(hir_info.body_span.lo()); - let term_for_bcb = |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); - let region_for_span = |span: Span| make_source_region(source_map, hir_info, &file, span); // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { @@ -160,22 +153,20 @@ fn create_mappings<'tcx>( } = extracted_mappings; let mut mappings = Vec::new(); - mappings.extend(code_mappings.iter().filter_map( + mappings.extend(code_mappings.iter().map( // Ordinary code mappings are the simplest kind. |&mappings::CodeMapping { span, bcb }| { - let source_region = region_for_span(span)?; let kind = MappingKind::Code(term_for_bcb(bcb)); - Some(Mapping { kind, source_region }) + Mapping { kind, span } }, )); - mappings.extend(branch_pairs.iter().filter_map( + mappings.extend(branch_pairs.iter().map( |&mappings::BranchPair { span, true_bcb, false_bcb }| { let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); let kind = MappingKind::Branch { true_term, false_term }; - let source_region = region_for_span(span)?; - Some(Mapping { kind, source_region }) + Mapping { kind, span } }, )); @@ -183,7 +174,7 @@ fn create_mappings<'tcx>( |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); // MCDC branch mappings are appended with their decisions in case decisions were ignored. - mappings.extend(mcdc_degraded_branches.iter().filter_map( + mappings.extend(mcdc_degraded_branches.iter().map( |&mappings::MCDCBranch { span, true_bcb, @@ -192,10 +183,9 @@ fn create_mappings<'tcx>( true_index: _, false_index: _, }| { - let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); - Some(Mapping { kind: MappingKind::Branch { true_term, false_term }, source_region }) + Mapping { kind: MappingKind::Branch { true_term, false_term }, span } }, )); @@ -203,7 +193,7 @@ fn create_mappings<'tcx>( let num_conditions = branches.len() as u16; let conditions = branches .into_iter() - .filter_map( + .map( |&mappings::MCDCBranch { span, true_bcb, @@ -212,31 +202,29 @@ fn create_mappings<'tcx>( true_index: _, false_index: _, }| { - let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); - Some(Mapping { + Mapping { kind: MappingKind::MCDCBranch { true_term, false_term, mcdc_params: condition_info, }, - source_region, - }) + span, + } }, ) .collect::>(); - if conditions.len() == num_conditions as usize - && let Some(source_region) = region_for_span(decision.span) - { + if conditions.len() == num_conditions as usize { // LLVM requires end index for counter mapping regions. let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx: (decision.bitmap_idx + decision.num_test_vectors) as u32, num_conditions, }); mappings.extend( - std::iter::once(Mapping { kind, source_region }).chain(conditions.into_iter()), + std::iter::once(Mapping { kind, span: decision.span }) + .chain(conditions.into_iter()), ); } else { mappings.extend(conditions.into_iter().map(|mapping| { @@ -245,10 +233,7 @@ fn create_mappings<'tcx>( else { unreachable!("all mappings here are MCDCBranch as shown above"); }; - Mapping { - kind: MappingKind::Branch { true_term, false_term }, - source_region: mapping.source_region, - } + Mapping { kind: MappingKind::Branch { true_term, false_term }, span: mapping.span } })) } } @@ -391,121 +376,6 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb data.statements.insert(0, statement); } -fn ensure_non_empty_span( - source_map: &SourceMap, - hir_info: &ExtractedHirInfo, - span: Span, -) -> Option { - if !span.is_empty() { - return Some(span); - } - - let lo = span.lo(); - let hi = span.hi(); - - // The span is empty, so try to expand it to cover an adjacent '{' or '}', - // but only within the bounds of the body span. - let try_next = hi < hir_info.body_span.hi(); - let try_prev = hir_info.body_span.lo() < lo; - if !(try_next || try_prev) { - return None; - } - - source_map - .span_to_source(span, |src, start, end| try { - // We're only checking for specific ASCII characters, so we don't - // have to worry about multi-byte code points. - if try_next && src.as_bytes()[end] == b'{' { - Some(span.with_hi(hi + BytePos(1))) - } else if try_prev && src.as_bytes()[start - 1] == b'}' { - Some(span.with_lo(lo - BytePos(1))) - } else { - None - } - }) - .ok()? -} - -/// Converts the span into its start line and column, and end line and column. -/// -/// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by -/// the compiler, these column numbers are denoted in **bytes**, because that's what -/// LLVM's `llvm-cov` tool expects to see in coverage maps. -/// -/// Returns `None` if the conversion failed for some reason. This shouldn't happen, -/// but it's hard to rule out entirely (especially in the presence of complex macros -/// or other expansions), and if it does happen then skipping a span or function is -/// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. -fn make_source_region( - source_map: &SourceMap, - hir_info: &ExtractedHirInfo, - file: &SourceFile, - span: Span, -) -> Option { - let span = ensure_non_empty_span(source_map, hir_info, span)?; - - let lo = span.lo(); - let hi = span.hi(); - - // Column numbers need to be in bytes, so we can't use the more convenient - // `SourceMap` methods for looking up file coordinates. - let line_and_byte_column = |pos: BytePos| -> Option<(usize, usize)> { - let rpos = file.relative_position(pos); - let line_index = file.lookup_line(rpos)?; - let line_start = file.lines()[line_index]; - // Line numbers and column numbers are 1-based, so add 1 to each. - Some((line_index + 1, (rpos - line_start).to_usize() + 1)) - }; - - let (mut start_line, start_col) = line_and_byte_column(lo)?; - let (mut end_line, end_col) = line_and_byte_column(hi)?; - - // Apply an offset so that code in doctests has correct line numbers. - // FIXME(#79417): Currently we have no way to offset doctest _columns_. - start_line = source_map.doctest_offset_line(&file.name, start_line); - end_line = source_map.doctest_offset_line(&file.name, end_line); - - check_source_region(SourceRegion { - start_line: start_line as u32, - start_col: start_col as u32, - end_line: end_line as u32, - end_col: end_col as u32, - }) -} - -/// If `llvm-cov` sees a source region that is improperly ordered (end < start), -/// it will immediately exit with a fatal error. To prevent that from happening, -/// discard regions that are improperly ordered, or might be interpreted in a -/// way that makes them improperly ordered. -fn check_source_region(source_region: SourceRegion) -> Option { - let SourceRegion { start_line, start_col, end_line, end_col } = source_region; - - // Line/column coordinates are supposed to be 1-based. If we ever emit - // coordinates of 0, `llvm-cov` might misinterpret them. - let all_nonzero = [start_line, start_col, end_line, end_col].into_iter().all(|x| x != 0); - // Coverage mappings use the high bit of `end_col` to indicate that a - // region is actually a "gap" region, so make sure it's unset. - let end_col_has_high_bit_unset = (end_col & (1 << 31)) == 0; - // If a region is improperly ordered (end < start), `llvm-cov` will exit - // with a fatal error, which is inconvenient for users and hard to debug. - let is_ordered = (start_line, start_col) <= (end_line, end_col); - - if all_nonzero && end_col_has_high_bit_unset && is_ordered { - Some(source_region) - } else { - debug!( - ?source_region, - ?all_nonzero, - ?end_col_has_high_bit_unset, - ?is_ordered, - "Skipping source region that would be misinterpreted or rejected by LLVM" - ); - // If this happens in a debug build, ICE to make it easier to notice. - debug_assert!(false, "Improper source region: {source_region:?}"); - None - } -} - /// Function information extracted from HIR by the coverage instrumentor. #[derive(Debug)] struct ExtractedHirInfo { diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index cbb11d50f79..39d52ba698a 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -33,12 +33,12 @@ + coverage ExpressionId(3) => Expression { lhs: Counter(3), op: Add, rhs: Counter(2) }; + coverage ExpressionId(4) => Expression { lhs: Expression(3), op: Add, rhs: Counter(1) }; + coverage ExpressionId(5) => Expression { lhs: Expression(4), op: Add, rhs: Expression(2) }; -+ coverage Code(Counter(0)) => 14:1 - 15:21; -+ coverage Code(Counter(3)) => 16:17 - 16:33; -+ coverage Code(Counter(2)) => 17:17 - 17:33; -+ coverage Code(Counter(1)) => 18:17 - 18:33; -+ coverage Code(Expression(2)) => 19:17 - 19:33; -+ coverage Code(Expression(5)) => 21:1 - 21:2; ++ coverage Code(Counter(0)) => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); ++ coverage Code(Counter(3)) => $DIR/branch_match_arms.rs:16:17: 16:33 (#0); ++ coverage Code(Counter(2)) => $DIR/branch_match_arms.rs:17:17: 17:33 (#0); ++ coverage Code(Counter(1)) => $DIR/branch_match_arms.rs:18:17: 18:33 (#0); ++ coverage Code(Expression(2)) => $DIR/branch_match_arms.rs:19:17: 19:33 (#0); ++ coverage Code(Expression(5)) => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index 2efb1fd0a17..148ff86354b 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -5,7 +5,7 @@ let mut _0: bool; + coverage body span: $DIR/instrument_coverage.rs:19:18: 21:2 (#0) -+ coverage Code(Counter(0)) => 19:1 - 21:2; ++ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:19:1: 21:2 (#0); + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index a179824d6c7..b480d1ac13a 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -9,11 +9,11 @@ + coverage body span: $DIR/instrument_coverage.rs:10:11: 16:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) }; -+ coverage Code(Counter(0)) => 10:1 - 10:11; -+ coverage Code(Expression(0)) => 12:12 - 12:17; -+ coverage Code(Counter(0)) => 13:13 - 13:18; -+ coverage Code(Counter(1)) => 14:9 - 14:10; -+ coverage Code(Counter(0)) => 16:1 - 16:2; ++ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:10:1: 10:11 (#0); ++ coverage Code(Expression(0)) => $DIR/instrument_coverage.rs:12:12: 12:17 (#0); ++ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:13:13: 13:18 (#0); ++ coverage Code(Counter(1)) => $DIR/instrument_coverage.rs:14:10: 14:10 (#0); ++ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:16:2: 16:2 (#0); + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index 082539369f7..2c7ec6e85eb 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -9,11 +9,11 @@ coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; - coverage Code(Counter(0)) => 13:1 - 14:36; - coverage Code(Expression(0)) => 14:37 - 14:39; - coverage Code(Counter(1)) => 14:38 - 14:39; - coverage Code(Counter(0)) => 15:1 - 15:2; - coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; + coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); + coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); + coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); + coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); + coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); bb0: { Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index 8635818c6a7..c08265eb0e9 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -9,11 +9,11 @@ + coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; -+ coverage Code(Counter(0)) => 13:1 - 14:36; -+ coverage Code(Expression(0)) => 14:37 - 14:39; -+ coverage Code(Counter(1)) => 14:38 - 14:39; -+ coverage Code(Counter(0)) => 15:1 - 15:2; -+ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; ++ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); ++ coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); ++ coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); ++ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); ++ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); + bb0: { + Coverage::CounterIncrement(0); -- cgit 1.4.1-3-g733a5 From 917dd826286bd85e26310e4db4a125d4038c277e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 1 Nov 2024 14:32:09 +0000 Subject: Do not unify dereferences in GVN. --- compiler/rustc_mir_transform/src/gvn.rs | 4 +- .../const_prop/read_immutable_static.main.GVN.diff | 14 +- tests/mir-opt/const_prop/read_immutable_static.rs | 2 +- tests/mir-opt/const_prop/ref_deref.main.GVN.diff | 3 +- .../const_prop/ref_deref_project.main.GVN.diff | 3 +- tests/mir-opt/const_prop/ref_deref_project.rs | 2 +- .../slice_len.main.GVN.32bit.panic-abort.diff | 9 +- .../slice_len.main.GVN.32bit.panic-unwind.diff | 9 +- .../slice_len.main.GVN.64bit.panic-abort.diff | 9 +- .../slice_len.main.GVN.64bit.panic-unwind.diff | 9 +- tests/mir-opt/const_prop/slice_len.rs | 4 +- tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff | 3 +- tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff | 3 +- .../mir-opt/gvn.dereferences.GVN.panic-abort.diff | 30 +-- .../mir-opt/gvn.dereferences.GVN.panic-unwind.diff | 30 +-- tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff | 18 +- .../mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff | 18 +- tests/mir-opt/gvn.rs | 38 ++-- tests/mir-opt/gvn.slices.GVN.panic-abort.diff | 38 ++-- tests/mir-opt/gvn.slices.GVN.panic-unwind.diff | 38 ++-- ....subexpression_elimination.GVN.panic-abort.diff | 50 ++--- ...subexpression_elimination.GVN.panic-unwind.diff | 50 ++--- .../mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff | 15 +- .../gvn_uninhabited.f.GVN.panic-unwind.diff | 15 +- tests/mir-opt/pre-codegen/deref_nested_borrows.rs | 4 +- .../deref_nested_borrows.src.GVN.panic-abort.diff | 7 +- .../deref_nested_borrows.src.GVN.panic-unwind.diff | 7 +- ...ed_borrows.src.PreCodegen.after.panic-abort.mir | 8 +- ...d_borrows.src.PreCodegen.after.panic-unwind.mir | 8 +- ...lter.variant_a-{closure#0}.PreCodegen.after.mir | 238 +++++++++++---------- ...lter.variant_b-{closure#0}.PreCodegen.after.mir | 54 ++--- 31 files changed, 351 insertions(+), 389 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 976f4a8e919..d5a813ec8ec 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -638,7 +638,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let proj = match proj { ProjectionElem::Deref => { let ty = place.ty(self.local_decls, self.tcx).ty; - if let Some(Mutability::Not) = ty.ref_mutability() + // unsound: https://github.com/rust-lang/rust/issues/130853 + if self.tcx.sess.opts.unstable_opts.unsound_mir_opts + && let Some(Mutability::Not) = ty.ref_mutability() && let Some(pointee_ty) = ty.builtin_deref(true) && pointee_ty.is_freeze(self.tcx, self.typing_env()) { diff --git a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff index 8df262b351f..23928337bf7 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff +++ b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff @@ -14,23 +14,19 @@ bb0: { StorageLive(_1); -- StorageLive(_2); + StorageLive(_2); - StorageLive(_3); -+ nop; + nop; _3 = const {ALLOC0: &u8}; -- _2 = copy (*_3); -+ _2 = const 2_u8; + _2 = copy (*_3); StorageLive(_4); StorageLive(_5); _5 = const {ALLOC0: &u8}; - _4 = copy (*_5); -- _1 = Add(move _2, move _4); -+ _4 = const 2_u8; -+ _1 = const 4_u8; ++ _4 = copy (*_3); + _1 = Add(move _2, move _4); StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageDead(_5); - StorageDead(_3); + nop; diff --git a/tests/mir-opt/const_prop/read_immutable_static.rs b/tests/mir-opt/const_prop/read_immutable_static.rs index 05fec2f3303..f88e4b3de93 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.rs +++ b/tests/mir-opt/const_prop/read_immutable_static.rs @@ -6,6 +6,6 @@ static FOO: u8 = 2; fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; - // CHECK: [[x]] = const 4_u8; + // CHECK-NOT: [[x]] = const 4_u8; let x = FOO + FOO; } diff --git a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff index b9e269266b0..4477b4b005b 100644 --- a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff @@ -16,8 +16,7 @@ StorageLive(_2); _4 = const main::promoted[0]; _2 = &(*_4); -- _1 = copy (*_2); -+ _1 = const 4_i32; + _1 = copy (*_2); StorageDead(_2); _0 = const (); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff index dcc13c9251c..bbfd70bea16 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff @@ -16,8 +16,7 @@ StorageLive(_2); _4 = const main::promoted[0]; _2 = &((*_4).1: i32); -- _1 = copy (*_2); -+ _1 = const 5_i32; + _1 = copy (*_2); StorageDead(_2); _0 = const (); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/ref_deref_project.rs b/tests/mir-opt/const_prop/ref_deref_project.rs index 5a48a887f93..813b4ae4745 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.rs +++ b/tests/mir-opt/const_prop/ref_deref_project.rs @@ -5,6 +5,6 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; - // CHECK: [[a]] = const 5_i32; + // CHECK-NOT: [[a]] = const 5_i32; let a = *(&(4, 5).1); } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff index 41ce94eda75..8a8ea5b7e20 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff @@ -30,17 +30,16 @@ StorageDead(_3); StorageLive(_6); _6 = const 1_usize; -- _7 = Len((*_2)); + _7 = Len((*_2)); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; ++ _8 = Lt(const 1_usize, copy _7); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { - _1 = copy (*_2)[_6]; -+ _1 = const 2_u32; ++ _1 = copy (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff index 8cced96cd43..f0c844884f6 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff @@ -30,17 +30,16 @@ StorageDead(_3); StorageLive(_6); _6 = const 1_usize; -- _7 = Len((*_2)); + _7 = Len((*_2)); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; ++ _8 = Lt(const 1_usize, copy _7); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { - _1 = copy (*_2)[_6]; -+ _1 = const 2_u32; ++ _1 = copy (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff index 41ce94eda75..8a8ea5b7e20 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff @@ -30,17 +30,16 @@ StorageDead(_3); StorageLive(_6); _6 = const 1_usize; -- _7 = Len((*_2)); + _7 = Len((*_2)); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; ++ _8 = Lt(const 1_usize, copy _7); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { - _1 = copy (*_2)[_6]; -+ _1 = const 2_u32; ++ _1 = copy (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff index 8cced96cd43..f0c844884f6 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff @@ -30,17 +30,16 @@ StorageDead(_3); StorageLive(_6); _6 = const 1_usize; -- _7 = Len((*_2)); + _7 = Len((*_2)); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; ++ _8 = Lt(const 1_usize, copy _7); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { - _1 = copy (*_2)[_6]; -+ _1 = const 2_u32; ++ _1 = copy (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index ebd3c9e792d..eb86e28408a 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -8,7 +8,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; // CHECK: [[slice:_.*]] = copy {{.*}} as &[u32] (PointerCoercion(Unsize, AsCast)); - // CHECK: assert(const true, - // CHECK: [[a]] = const 2_u32; + // CHECK-NOT: assert(const true, + // CHECK-NOT: [[a]] = const 2_u32; let a = (&[1u32, 2, 3] as &[u32])[1]; } diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff index b0702696e18..acbea13642c 100644 --- a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff @@ -18,8 +18,7 @@ } bb2: { -- _0 = opaque::(copy (*_3)) -> [return: bb3, unwind unreachable]; -+ _0 = opaque::(copy _1) -> [return: bb3, unwind unreachable]; + _0 = opaque::(copy (*_3)) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff index fe05d4deeed..ba080bfdb07 100644 --- a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff @@ -18,8 +18,7 @@ } bb2: { -- _0 = opaque::(copy (*_3)) -> [return: bb3, unwind continue]; -+ _0 = opaque::(copy _1) -> [return: bb3, unwind continue]; + _0 = opaque::(copy (*_3)) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff index a763614dc64..ecd7bdc433c 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff @@ -107,23 +107,18 @@ StorageLive(_18); _18 = &(*_1); StorageLive(_19); -- StorageLive(_20); -+ nop; + StorageLive(_20); _20 = copy (*_18); -- _19 = opaque::(move _20) -> [return: bb7, unwind unreachable]; -+ _19 = opaque::(copy _20) -> [return: bb7, unwind unreachable]; + _19 = opaque::(move _20) -> [return: bb7, unwind unreachable]; } bb7: { -- StorageDead(_20); -+ nop; + StorageDead(_20); StorageDead(_19); StorageLive(_21); StorageLive(_22); -- _22 = copy (*_18); -- _21 = opaque::(move _22) -> [return: bb8, unwind unreachable]; -+ _22 = copy _20; -+ _21 = opaque::(copy _20) -> [return: bb8, unwind unreachable]; + _22 = copy (*_18); + _21 = opaque::(move _22) -> [return: bb8, unwind unreachable]; } bb8: { @@ -157,23 +152,18 @@ StorageDead(_28); StorageDead(_27); StorageLive(_29); -- StorageLive(_30); -+ nop; + StorageLive(_30); _30 = copy ((*_3).0: u32); -- _29 = opaque::(move _30) -> [return: bb12, unwind unreachable]; -+ _29 = opaque::(copy _30) -> [return: bb12, unwind unreachable]; + _29 = opaque::(move _30) -> [return: bb12, unwind unreachable]; } bb12: { -- StorageDead(_30); -+ nop; + StorageDead(_30); StorageDead(_29); StorageLive(_31); StorageLive(_32); -- _32 = copy ((*_3).0: u32); -- _31 = opaque::(move _32) -> [return: bb13, unwind unreachable]; -+ _32 = copy _30; -+ _31 = opaque::(copy _30) -> [return: bb13, unwind unreachable]; + _32 = copy ((*_3).0: u32); + _31 = opaque::(move _32) -> [return: bb13, unwind unreachable]; } bb13: { diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff index ca6fda48364..bbca6bc3c75 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff @@ -107,23 +107,18 @@ StorageLive(_18); _18 = &(*_1); StorageLive(_19); -- StorageLive(_20); -+ nop; + StorageLive(_20); _20 = copy (*_18); -- _19 = opaque::(move _20) -> [return: bb7, unwind continue]; -+ _19 = opaque::(copy _20) -> [return: bb7, unwind continue]; + _19 = opaque::(move _20) -> [return: bb7, unwind continue]; } bb7: { -- StorageDead(_20); -+ nop; + StorageDead(_20); StorageDead(_19); StorageLive(_21); StorageLive(_22); -- _22 = copy (*_18); -- _21 = opaque::(move _22) -> [return: bb8, unwind continue]; -+ _22 = copy _20; -+ _21 = opaque::(copy _20) -> [return: bb8, unwind continue]; + _22 = copy (*_18); + _21 = opaque::(move _22) -> [return: bb8, unwind continue]; } bb8: { @@ -157,23 +152,18 @@ StorageDead(_28); StorageDead(_27); StorageLive(_29); -- StorageLive(_30); -+ nop; + StorageLive(_30); _30 = copy ((*_3).0: u32); -- _29 = opaque::(move _30) -> [return: bb12, unwind continue]; -+ _29 = opaque::(copy _30) -> [return: bb12, unwind continue]; + _29 = opaque::(move _30) -> [return: bb12, unwind continue]; } bb12: { -- StorageDead(_30); -+ nop; + StorageDead(_30); StorageDead(_29); StorageLive(_31); StorageLive(_32); -- _32 = copy ((*_3).0: u32); -- _31 = opaque::(move _32) -> [return: bb13, unwind continue]; -+ _32 = copy _30; -+ _31 = opaque::(copy _30) -> [return: bb13, unwind continue]; + _32 = copy ((*_3).0: u32); + _31 = opaque::(move _32) -> [return: bb13, unwind continue]; } bb13: { diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index 130b011630c..3cce35d34e9 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:614:19: 614:21}; + let mut _9: {closure@$DIR/gvn.rs:620:19: 620:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:614:19: 614:21}; + let mut _13: {closure@$DIR/gvn.rs:620:19: 620:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:614:19: 614:21}; + let _7: {closure@$DIR/gvn.rs:620:19: 620:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:614:19: 614:21}; +- _7 = {closure@$DIR/gvn.rs:620:19: 620:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index 372a08d5473..d85aca040fe 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:614:19: 614:21}; + let mut _9: {closure@$DIR/gvn.rs:620:19: 620:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:614:19: 614:21}; + let mut _13: {closure@$DIR/gvn.rs:620:19: 620:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:614:19: 614:21}; + let _7: {closure@$DIR/gvn.rs:620:19: 620:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:614:19: 614:21}; +- _7 = {closure@$DIR/gvn.rs:620:19: 620:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index faa6faa7017..bb9435adebd 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -99,12 +99,14 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { opaque((x * y) - y); opaque((x * y) - y); - // We can substitute through an immutable reference too. + // We cannot substitute through an immutable reference. // CHECK: [[ref:_.*]] = &_3; // CHECK: [[deref:_.*]] = copy (*[[ref]]); - // CHECK: [[addref:_.*]] = Add(copy [[deref]], copy _1); - // CHECK: opaque::(copy [[addref]]) - // CHECK: opaque::(copy [[addref]]) + // CHECK: [[addref:_.*]] = Add(move [[deref]], copy _1); + // CHECK: opaque::(move [[addref]]) + // CHECK: [[deref2:_.*]] = copy (*[[ref]]); + // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); + // CHECK: opaque::(move [[addref2]]) let a = &z; opaque(*a + x); opaque(*a + x); @@ -137,13 +139,15 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { opaque(*d + x); } - // We can substitute again, but not with the earlier computations. + // We still cannot substitute again, and never with the earlier computations. // Important: `e` is not `a`! // CHECK: [[ref2:_.*]] = &_3; // CHECK: [[deref2:_.*]] = copy (*[[ref2]]); - // CHECK: [[addref2:_.*]] = Add(copy [[deref2]], copy _1); - // CHECK: opaque::(copy [[addref2]]) - // CHECK: opaque::(copy [[addref2]]) + // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); + // CHECK: opaque::(move [[addref2]]) + // CHECK: [[deref3:_.*]] = copy (*[[ref2]]); + // CHECK: [[addref3:_.*]] = Add(move [[deref3]], copy _1); + // CHECK: opaque::(move [[addref3]]) let e = &z; opaque(*e + x); opaque(*e + x); @@ -495,15 +499,16 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { unsafe { opaque(*z) }; unsafe { opaque(*z) }; - // We can reuse dereferences of `&Freeze`. + // Do not reuse dereferences of `&Freeze`. // CHECK: [[ref:_.*]] = &(*_1); // CHECK: [[st7:_.*]] = copy (*[[ref]]); - // CHECK: opaque::(copy [[st7]]) - // CHECK: opaque::(copy [[st7]]) + // CHECK: opaque::(move [[st7]]) + // CHECK: [[st8:_.*]] = copy (*[[ref]]); + // CHECK: opaque::(move [[st8]]) let z = &*t; opaque(*z); opaque(*z); - // But not in reborrows. + // Not in reborrows either. // CHECK: [[reborrow:_.*]] = &(*[[ref]]); // CHECK: opaque::<&u32>(move [[reborrow]]) opaque(&*z); @@ -516,10 +521,11 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { opaque(*u); opaque(*u); - // `*s` is not Copy, but `(*s).0` is, so we can reuse. + // `*s` is not Copy, but `(*s).0` is, but we still cannot reuse. // CHECK: [[st10:_.*]] = copy ((*_3).0: u32); - // CHECK: opaque::(copy [[st10]]) - // CHECK: opaque::(copy [[st10]]) + // CHECK: opaque::(move [[st10]]) + // CHECK: [[st11:_.*]] = copy ((*_3).0: u32); + // CHECK: opaque::(move [[st11]]) opaque(s.0); opaque(s.0); } @@ -736,7 +742,7 @@ fn borrowed(x: T) { // CHECK: bb1: { // CHECK-NEXT: _0 = opaque::(copy _1) // CHECK: bb2: { - // CHECK-NEXT: _0 = opaque::(copy _1) + // CHECK-NEXT: _0 = opaque::(copy (*_3)) mir! { { let a = x; diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff index e8e99b44e72..43efcbdfb1e 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -111,9 +111,8 @@ StorageLive(_7); StorageLive(_8); - StorageLive(_9); -- StorageLive(_10); -+ nop; + nop; + StorageLive(_10); StorageLive(_11); _11 = &(*_1); _10 = core::str::::as_ptr(move _11) -> [return: bb3, unwind unreachable]; @@ -123,9 +122,8 @@ StorageDead(_11); _9 = &_10; - StorageLive(_12); -- StorageLive(_13); -+ nop; + nop; + StorageLive(_13); StorageLive(_14); - _14 = &(*_4); + _14 = &(*_1); @@ -150,12 +148,11 @@ StorageLive(_17); StorageLive(_18); - _18 = copy (*_15); -+ _18 = copy _10; ++ _18 = copy (*_9); StorageLive(_19); - _19 = copy (*_16); -- _17 = Eq(move _18, move _19); -+ _19 = copy _13; -+ _17 = Eq(copy _10, copy _13); ++ _19 = copy (*_12); + _17 = Eq(move _18, move _19); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -166,10 +163,8 @@ StorageDead(_17); StorageDead(_16); StorageDead(_15); -- StorageDead(_13); -- StorageDead(_10); -+ nop; -+ nop; + StorageDead(_13); + StorageDead(_10); StorageDead(_8); StorageDead(_7); - StorageLive(_29); @@ -218,9 +213,8 @@ StorageLive(_33); StorageLive(_34); - StorageLive(_35); -- StorageLive(_36); -+ nop; + nop; + StorageLive(_36); StorageLive(_37); _37 = &(*_1); _36 = core::str::::as_ptr(move _37) -> [return: bb8, unwind unreachable]; @@ -230,9 +224,8 @@ StorageDead(_37); _35 = &_36; - StorageLive(_38); -- StorageLive(_39); -+ nop; + nop; + StorageLive(_39); StorageLive(_40); _40 = &(*_29); _39 = core::slice::::as_ptr(move _40) -> [return: bb9, unwind unreachable]; @@ -256,12 +249,11 @@ StorageLive(_43); StorageLive(_44); - _44 = copy (*_41); -+ _44 = copy _36; ++ _44 = copy (*_35); StorageLive(_45); - _45 = copy (*_42); -- _43 = Eq(move _44, move _45); -+ _45 = copy _39; -+ _43 = Eq(copy _36, copy _39); ++ _45 = copy (*_38); + _43 = Eq(move _44, move _45); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } @@ -272,10 +264,8 @@ StorageDead(_43); StorageDead(_42); StorageDead(_41); -- StorageDead(_39); -- StorageDead(_36); -+ nop; -+ nop; + StorageDead(_39); + StorageDead(_36); StorageDead(_34); StorageDead(_33); _0 = const (); diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff index 4296d4d4a59..8572f538c0f 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -111,9 +111,8 @@ StorageLive(_7); StorageLive(_8); - StorageLive(_9); -- StorageLive(_10); -+ nop; + nop; + StorageLive(_10); StorageLive(_11); _11 = &(*_1); _10 = core::str::::as_ptr(move _11) -> [return: bb3, unwind continue]; @@ -123,9 +122,8 @@ StorageDead(_11); _9 = &_10; - StorageLive(_12); -- StorageLive(_13); -+ nop; + nop; + StorageLive(_13); StorageLive(_14); - _14 = &(*_4); + _14 = &(*_1); @@ -150,12 +148,11 @@ StorageLive(_17); StorageLive(_18); - _18 = copy (*_15); -+ _18 = copy _10; ++ _18 = copy (*_9); StorageLive(_19); - _19 = copy (*_16); -- _17 = Eq(move _18, move _19); -+ _19 = copy _13; -+ _17 = Eq(copy _10, copy _13); ++ _19 = copy (*_12); + _17 = Eq(move _18, move _19); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -166,10 +163,8 @@ StorageDead(_17); StorageDead(_16); StorageDead(_15); -- StorageDead(_13); -- StorageDead(_10); -+ nop; -+ nop; + StorageDead(_13); + StorageDead(_10); StorageDead(_8); StorageDead(_7); - StorageLive(_29); @@ -218,9 +213,8 @@ StorageLive(_33); StorageLive(_34); - StorageLive(_35); -- StorageLive(_36); -+ nop; + nop; + StorageLive(_36); StorageLive(_37); _37 = &(*_1); _36 = core::str::::as_ptr(move _37) -> [return: bb8, unwind continue]; @@ -230,9 +224,8 @@ StorageDead(_37); _35 = &_36; - StorageLive(_38); -- StorageLive(_39); -+ nop; + nop; + StorageLive(_39); StorageLive(_40); _40 = &(*_29); _39 = core::slice::::as_ptr(move _40) -> [return: bb9, unwind continue]; @@ -256,12 +249,11 @@ StorageLive(_43); StorageLive(_44); - _44 = copy (*_41); -+ _44 = copy _36; ++ _44 = copy (*_35); StorageLive(_45); - _45 = copy (*_42); -- _43 = Eq(move _44, move _45); -+ _45 = copy _39; -+ _43 = Eq(copy _36, copy _39); ++ _45 = copy (*_38); + _43 = Eq(move _44, move _45); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } @@ -272,10 +264,8 @@ StorageDead(_43); StorageDead(_42); StorageDead(_41); -- StorageDead(_39); -- StorageDead(_36); -+ nop; -+ nop; + StorageDead(_39); + StorageDead(_36); StorageDead(_34); StorageDead(_33); _0 = const (); diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff index 7a479bc55da..e872e011542 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -758,39 +758,32 @@ StorageLive(_126); _126 = &_3; StorageLive(_127); -- StorageLive(_128); -- StorageLive(_129); -+ nop; -+ nop; + StorageLive(_128); + StorageLive(_129); _129 = copy (*_126); StorageLive(_130); _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(copy _129, copy _1); ++ _128 = Add(move _129, copy _1); StorageDead(_130); -- StorageDead(_129); -- _127 = opaque::(move _128) -> [return: bb35, unwind unreachable]; -+ nop; -+ _127 = opaque::(copy _128) -> [return: bb35, unwind unreachable]; + StorageDead(_129); + _127 = opaque::(move _128) -> [return: bb35, unwind unreachable]; } bb35: { -- StorageDead(_128); -+ nop; + StorageDead(_128); StorageDead(_127); StorageLive(_131); StorageLive(_132); StorageLive(_133); -- _133 = copy (*_126); -+ _133 = copy _129; + _133 = copy (*_126); StorageLive(_134); _134 = copy _1; - _132 = Add(move _133, move _134); -+ _132 = copy _128; ++ _132 = Add(move _133, copy _1); StorageDead(_134); StorageDead(_133); -- _131 = opaque::(move _132) -> [return: bb36, unwind unreachable]; -+ _131 = opaque::(copy _128) -> [return: bb36, unwind unreachable]; + _131 = opaque::(move _132) -> [return: bb36, unwind unreachable]; } bb36: { @@ -906,39 +899,32 @@ StorageLive(_163); _163 = &_3; StorageLive(_164); -- StorageLive(_165); -- StorageLive(_166); -+ nop; -+ nop; + StorageLive(_165); + StorageLive(_166); _166 = copy (*_163); StorageLive(_167); _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(copy _166, copy _1); ++ _165 = Add(move _166, copy _1); StorageDead(_167); -- StorageDead(_166); -- _164 = opaque::(move _165) -> [return: bb43, unwind unreachable]; -+ nop; -+ _164 = opaque::(copy _165) -> [return: bb43, unwind unreachable]; + StorageDead(_166); + _164 = opaque::(move _165) -> [return: bb43, unwind unreachable]; } bb43: { -- StorageDead(_165); -+ nop; + StorageDead(_165); StorageDead(_164); StorageLive(_168); StorageLive(_169); StorageLive(_170); -- _170 = copy (*_163); -+ _170 = copy _166; + _170 = copy (*_163); StorageLive(_171); _171 = copy _1; - _169 = Add(move _170, move _171); -+ _169 = copy _165; ++ _169 = Add(move _170, copy _1); StorageDead(_171); StorageDead(_170); -- _168 = opaque::(move _169) -> [return: bb44, unwind unreachable]; -+ _168 = opaque::(copy _165) -> [return: bb44, unwind unreachable]; + _168 = opaque::(move _169) -> [return: bb44, unwind unreachable]; } bb44: { diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff index 3ca5238663c..3996dab27a3 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -758,39 +758,32 @@ StorageLive(_126); _126 = &_3; StorageLive(_127); -- StorageLive(_128); -- StorageLive(_129); -+ nop; -+ nop; + StorageLive(_128); + StorageLive(_129); _129 = copy (*_126); StorageLive(_130); _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(copy _129, copy _1); ++ _128 = Add(move _129, copy _1); StorageDead(_130); -- StorageDead(_129); -- _127 = opaque::(move _128) -> [return: bb35, unwind continue]; -+ nop; -+ _127 = opaque::(copy _128) -> [return: bb35, unwind continue]; + StorageDead(_129); + _127 = opaque::(move _128) -> [return: bb35, unwind continue]; } bb35: { -- StorageDead(_128); -+ nop; + StorageDead(_128); StorageDead(_127); StorageLive(_131); StorageLive(_132); StorageLive(_133); -- _133 = copy (*_126); -+ _133 = copy _129; + _133 = copy (*_126); StorageLive(_134); _134 = copy _1; - _132 = Add(move _133, move _134); -+ _132 = copy _128; ++ _132 = Add(move _133, copy _1); StorageDead(_134); StorageDead(_133); -- _131 = opaque::(move _132) -> [return: bb36, unwind continue]; -+ _131 = opaque::(copy _128) -> [return: bb36, unwind continue]; + _131 = opaque::(move _132) -> [return: bb36, unwind continue]; } bb36: { @@ -906,39 +899,32 @@ StorageLive(_163); _163 = &_3; StorageLive(_164); -- StorageLive(_165); -- StorageLive(_166); -+ nop; -+ nop; + StorageLive(_165); + StorageLive(_166); _166 = copy (*_163); StorageLive(_167); _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(copy _166, copy _1); ++ _165 = Add(move _166, copy _1); StorageDead(_167); -- StorageDead(_166); -- _164 = opaque::(move _165) -> [return: bb43, unwind continue]; -+ nop; -+ _164 = opaque::(copy _165) -> [return: bb43, unwind continue]; + StorageDead(_166); + _164 = opaque::(move _165) -> [return: bb43, unwind continue]; } bb43: { -- StorageDead(_165); -+ nop; + StorageDead(_165); StorageDead(_164); StorageLive(_168); StorageLive(_169); StorageLive(_170); -- _170 = copy (*_163); -+ _170 = copy _166; + _170 = copy (*_163); StorageLive(_171); _171 = copy _1; - _169 = Add(move _170, move _171); -+ _169 = copy _165; ++ _169 = Add(move _170, copy _1); StorageDead(_171); StorageDead(_170); -- _168 = opaque::(move _169) -> [return: bb44, unwind continue]; -+ _168 = opaque::(copy _165) -> [return: bb44, unwind continue]; + _168 = opaque::(move _169) -> [return: bb44, unwind continue]; } bb44: { diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff index 37b7b0d2c9d..881b629803a 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff @@ -17,16 +17,15 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); -- _2 = copy ((*_3).1: E); -+ _2 = copy ((*_5).1: E); - StorageLive(_1); -- _1 = copy ((_2 as A).1: u32); -+ _1 = const 0_u32; + _2 = copy ((*_3).1: E); +- StorageLive(_1); ++ nop; + _1 = copy ((_2 as A).1: u32); StorageDead(_3); StorageDead(_2); -- _0 = copy _1; -+ _0 = const 0_u32; - StorageDead(_1); + _0 = copy _1; +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff index 37b7b0d2c9d..881b629803a 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff @@ -17,16 +17,15 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); -- _2 = copy ((*_3).1: E); -+ _2 = copy ((*_5).1: E); - StorageLive(_1); -- _1 = copy ((_2 as A).1: u32); -+ _1 = const 0_u32; + _2 = copy ((*_3).1: E); +- StorageLive(_1); ++ nop; + _1 = copy ((_2 as A).1: u32); StorageDead(_3); StorageDead(_2); -- _0 = copy _1; -+ _0 = const 0_u32; - StorageDead(_1); + _0 = copy _1; +- StorageDead(_1); ++ nop; return; } } diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs index ba23d5d2b25..738cd981ae6 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs @@ -2,7 +2,9 @@ fn src(x: &&u8) -> bool { // CHECK-LABEL: fn src( - // CHECK: _0 = const true; + // CHECK-NOT: _0 = const true; + // CHECK: _0 = Eq({{.*}}, {{.*}}); + // CHECK-NOT: _0 = const true; let y = **x; unsafe { unknown() }; **x == y diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff index 838f5e6839f..993857f225a 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff @@ -26,13 +26,12 @@ bb1: { StorageLive(_4); - _7 = deref_copy (*_1); -- _4 = copy (*_7); -+ _7 = copy _6; -+ _4 = copy _2; ++ _7 = copy (*_1); + _4 = copy (*_7); StorageLive(_5); _5 = copy _2; - _0 = Eq(move _4, move _5); -+ _0 = const true; ++ _0 = Eq(move _4, copy _2); StorageDead(_5); StorageDead(_4); - StorageDead(_2); diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff index 25445a9a47e..d81bfa9310b 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff @@ -26,13 +26,12 @@ bb1: { StorageLive(_4); - _7 = deref_copy (*_1); -- _4 = copy (*_7); -+ _7 = copy _6; -+ _4 = copy _2; ++ _7 = copy (*_1); + _4 = copy (*_7); StorageLive(_5); _5 = copy _2; - _0 = Eq(move _4, move _5); -+ _0 = const true; ++ _0 = Eq(move _4, copy _2); StorageDead(_5); StorageDead(_4); - StorageDead(_2); diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir index 13f2eb9874b..23b1c3f3f43 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir @@ -6,6 +6,8 @@ fn src(_1: &&u8) -> bool { let mut _2: &u8; let _3: u8; let _4: (); + let mut _5: &u8; + let mut _6: u8; scope 1 { debug y => _3; } @@ -17,7 +19,11 @@ fn src(_1: &&u8) -> bool { } bb1: { - _0 = const true; + StorageLive(_6); + _5 = copy (*_1); + _6 = copy (*_5); + _0 = Eq(move _6, copy _3); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir index 7fab6e5511f..4c01e9464bf 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir @@ -6,6 +6,8 @@ fn src(_1: &&u8) -> bool { let mut _2: &u8; let _3: u8; let _4: (); + let mut _5: &u8; + let mut _6: u8; scope 1 { debug y => _3; } @@ -17,7 +19,11 @@ fn src(_1: &&u8) -> bool { } bb1: { - _0 = const true; + StorageLive(_6); + _5 = copy (*_1); + _6 = copy (*_5); + _0 = Eq(move _6, copy _3); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index cbdd194afd3..5a269717f82 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -4,65 +4,70 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: &usize; - let _5: &usize; + let mut _5: &(usize, usize, usize, usize); let _6: &usize; - let _7: &usize; - let mut _8: &&usize; - let _9: &usize; - let mut _10: &&usize; - let mut _13: bool; - let mut _14: &&usize; - let _15: &usize; - let mut _16: &&usize; - let mut _19: bool; - let mut _20: &&usize; - let _21: &usize; - let mut _22: &&usize; - let mut _23: bool; - let mut _24: &&usize; - let _25: &usize; - let mut _26: &&usize; + let mut _7: &(usize, usize, usize, usize); + let _8: &usize; + let mut _9: &(usize, usize, usize, usize); + let _10: &usize; + let mut _11: &&usize; + let _12: &usize; + let mut _13: &&usize; + let mut _16: bool; + let mut _17: &&usize; + let _18: &usize; + let mut _19: &&usize; + let mut _22: bool; + let mut _23: &&usize; + let _24: &usize; + let mut _25: &&usize; + let mut _28: bool; + let mut _29: &&usize; + let _30: &usize; + let mut _31: &&usize; scope 1 { debug a => _4; - debug b => _5; - debug c => _6; - debug d => _7; + debug b => _6; + debug c => _8; + debug d => _10; scope 2 (inlined std::cmp::impls::::le) { - debug self => _8; - debug other => _10; + debug self => _11; + debug other => _13; scope 3 (inlined std::cmp::impls::::le) { debug self => _4; - debug other => _6; - let mut _11: usize; - let mut _12: usize; + debug other => _8; + let mut _14: usize; + let mut _15: usize; } } scope 4 (inlined std::cmp::impls::::le) { - debug self => _14; - debug other => _16; + debug self => _17; + debug other => _19; scope 5 (inlined std::cmp::impls::::le) { - debug self => _7; - debug other => _5; - let mut _17: usize; - let mut _18: usize; + debug self => _10; + debug other => _6; + let mut _20: usize; + let mut _21: usize; } } scope 6 (inlined std::cmp::impls::::le) { - debug self => _20; - debug other => _22; + debug self => _23; + debug other => _25; scope 7 (inlined std::cmp::impls::::le) { - debug self => _6; + debug self => _8; debug other => _4; + let mut _26: usize; + let mut _27: usize; } } scope 8 (inlined std::cmp::impls::::le) { - debug self => _24; - debug other => _26; + debug self => _29; + debug other => _31; scope 9 (inlined std::cmp::impls::::le) { - debug self => _5; - debug other => _7; - let mut _27: usize; - let mut _28: usize; + debug self => _6; + debug other => _10; + let mut _32: usize; + let mut _33: usize; } } } @@ -70,116 +75,129 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 bb0: { _3 = copy (*_2); _4 = &((*_3).0: usize); - _5 = &((*_3).1: usize); - _6 = &((*_3).2: usize); - _7 = &((*_3).3: usize); + _5 = copy (*_2); + _6 = &((*_5).1: usize); + _7 = copy (*_2); + _8 = &((*_7).2: usize); + _9 = copy (*_2); + _10 = &((*_9).3: usize); + StorageLive(_16); + StorageLive(_11); + _11 = &_4; StorageLive(_13); - StorageLive(_8); - _8 = &_4; - StorageLive(_10); - StorageLive(_9); - _9 = copy _6; - _10 = &_9; - _11 = copy ((*_3).0: usize); - _12 = copy ((*_3).2: usize); - _13 = Le(copy _11, copy _12); - switchInt(move _13) -> [0: bb1, otherwise: bb2]; + StorageLive(_12); + _12 = copy _8; + _13 = &_12; + StorageLive(_14); + _14 = copy ((*_3).0: usize); + StorageLive(_15); + _15 = copy ((*_7).2: usize); + _16 = Le(move _14, move _15); + StorageDead(_15); + StorageDead(_14); + switchInt(move _16) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageDead(_9); - StorageDead(_10); - StorageDead(_8); + StorageDead(_12); + StorageDead(_13); + StorageDead(_11); goto -> bb4; } bb2: { - StorageDead(_9); - StorageDead(_10); - StorageDead(_8); - StorageLive(_19); - StorageLive(_14); - _14 = &_7; - StorageLive(_16); - StorageLive(_15); - _15 = copy _5; - _16 = &_15; + StorageDead(_12); + StorageDead(_13); + StorageDead(_11); + StorageLive(_22); StorageLive(_17); - _17 = copy ((*_3).3: usize); + _17 = &_10; + StorageLive(_19); StorageLive(_18); - _18 = copy ((*_3).1: usize); - _19 = Le(move _17, move _18); - StorageDead(_18); - StorageDead(_17); - switchInt(move _19) -> [0: bb3, otherwise: bb8]; + _18 = copy _6; + _19 = &_18; + StorageLive(_20); + _20 = copy ((*_9).3: usize); + StorageLive(_21); + _21 = copy ((*_5).1: usize); + _22 = Le(move _20, move _21); + StorageDead(_21); + StorageDead(_20); + switchInt(move _22) -> [0: bb3, otherwise: bb8]; } bb3: { - StorageDead(_15); - StorageDead(_16); - StorageDead(_14); + StorageDead(_18); + StorageDead(_19); + StorageDead(_17); goto -> bb4; } bb4: { + StorageLive(_28); StorageLive(_23); - StorageLive(_20); - _20 = &_6; - StorageLive(_22); - StorageLive(_21); - _21 = copy _4; - _22 = &_21; - _23 = Le(copy _12, copy _11); - switchInt(move _23) -> [0: bb5, otherwise: bb6]; + _23 = &_8; + StorageLive(_25); + StorageLive(_24); + _24 = copy _4; + _25 = &_24; + StorageLive(_26); + _26 = copy ((*_7).2: usize); + StorageLive(_27); + _27 = copy ((*_3).0: usize); + _28 = Le(move _26, move _27); + StorageDead(_27); + StorageDead(_26); + switchInt(move _28) -> [0: bb5, otherwise: bb6]; } bb5: { - StorageDead(_21); - StorageDead(_22); - StorageDead(_20); + StorageDead(_24); + StorageDead(_25); + StorageDead(_23); _0 = const false; goto -> bb7; } bb6: { - StorageDead(_21); - StorageDead(_22); - StorageDead(_20); - StorageLive(_24); - _24 = &_5; - StorageLive(_26); - StorageLive(_25); - _25 = copy _7; - _26 = &_25; - StorageLive(_27); - _27 = copy ((*_3).1: usize); - StorageLive(_28); - _28 = copy ((*_3).3: usize); - _0 = Le(move _27, move _28); - StorageDead(_28); - StorageDead(_27); - StorageDead(_25); - StorageDead(_26); StorageDead(_24); + StorageDead(_25); + StorageDead(_23); + StorageLive(_29); + _29 = &_6; + StorageLive(_31); + StorageLive(_30); + _30 = copy _10; + _31 = &_30; + StorageLive(_32); + _32 = copy ((*_5).1: usize); + StorageLive(_33); + _33 = copy ((*_9).3: usize); + _0 = Le(move _32, move _33); + StorageDead(_33); + StorageDead(_32); + StorageDead(_30); + StorageDead(_31); + StorageDead(_29); goto -> bb7; } bb7: { - StorageDead(_23); + StorageDead(_28); goto -> bb9; } bb8: { - StorageDead(_15); - StorageDead(_16); - StorageDead(_14); + StorageDead(_18); + StorageDead(_19); + StorageDead(_17); _0 = const true; goto -> bb9; } bb9: { - StorageDead(_19); - StorageDead(_13); + StorageDead(_22); + StorageDead(_16); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir index bc7a31d5219..f93f7264dec 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir @@ -4,40 +4,46 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: usize; - let _5: usize; + let mut _5: &(usize, usize, usize, usize); let _6: usize; - let _7: usize; - let mut _8: bool; - let mut _9: bool; - let mut _10: bool; + let mut _7: &(usize, usize, usize, usize); + let _8: usize; + let mut _9: &(usize, usize, usize, usize); + let _10: usize; + let mut _11: bool; + let mut _12: bool; + let mut _13: bool; scope 1 { debug a => _4; - debug b => _5; - debug c => _6; - debug d => _7; + debug b => _6; + debug c => _8; + debug d => _10; } bb0: { _3 = copy (*_2); _4 = copy ((*_3).0: usize); - _5 = copy ((*_3).1: usize); - _6 = copy ((*_3).2: usize); - _7 = copy ((*_3).3: usize); - StorageLive(_8); - _8 = Le(copy _4, copy _6); - switchInt(move _8) -> [0: bb2, otherwise: bb1]; + _5 = copy (*_2); + _6 = copy ((*_5).1: usize); + _7 = copy (*_2); + _8 = copy ((*_7).2: usize); + _9 = copy (*_2); + _10 = copy ((*_9).3: usize); + StorageLive(_11); + _11 = Le(copy _4, copy _8); + switchInt(move _11) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageLive(_9); - _9 = Le(copy _7, copy _5); - switchInt(move _9) -> [0: bb2, otherwise: bb6]; + StorageLive(_12); + _12 = Le(copy _10, copy _6); + switchInt(move _12) -> [0: bb2, otherwise: bb6]; } bb2: { - StorageLive(_10); - _10 = Le(copy _6, copy _4); - switchInt(move _10) -> [0: bb3, otherwise: bb4]; + StorageLive(_13); + _13 = Le(copy _8, copy _4); + switchInt(move _13) -> [0: bb3, otherwise: bb4]; } bb3: { @@ -46,12 +52,12 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb4: { - _0 = Le(copy _5, copy _7); + _0 = Le(copy _6, copy _10); goto -> bb5; } bb5: { - StorageDead(_10); + StorageDead(_13); goto -> bb7; } @@ -61,8 +67,8 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb7: { - StorageDead(_9); - StorageDead(_8); + StorageDead(_12); + StorageDead(_11); return; } } -- cgit 1.4.1-3-g733a5 From be7c6a3b43a8d200ba29f5a768e32287bb95aec2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Nov 2024 16:04:03 +1100 Subject: Make it possible for `ResultsCursor` to borrow a `Results`. `ResultsCursor` currently owns its `Results`. But sometimes the `Results` is needed again afterwards. So there is `ResultsCursor::into_results` for extracting the `Results`, which leads to some awkwardness. This commit adds `ResultsHandle`, a `Cow`-like type that can either borrow or own a a `Results`. `ResultsCursor` now uses it. This is good because some `ResultsCursor`s really want to own their `Results`, while others just want to borrow it. We end with with a few more lines of code, but get some nice cleanups. - `ResultsCursor::into_results` and `Formatter::into_results` are removed. - `write_graphviz_results` now just borrows a `Results`, instead of the awkward "take ownership of a `Results` and then return it unchanged" pattern. This reinstates the cursor flexibility that was lost in #118230 -- which removed the old `ResultsRefCursor` and `ResultsCloneCursor` types -- but in a much simpler way. Hooray! --- .../rustc_mir_dataflow/src/framework/cursor.rs | 51 +++++++++++++++++++--- .../rustc_mir_dataflow/src/framework/graphviz.rs | 8 +--- compiler/rustc_mir_dataflow/src/framework/mod.rs | 7 ++- .../rustc_mir_dataflow/src/framework/results.rs | 35 +++++++++++---- compiler/rustc_mir_transform/src/coroutine.rs | 11 +++-- 5 files changed, 81 insertions(+), 31 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index fbd9376917a..11cf8c3e898 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -1,6 +1,7 @@ //! Random access inspection of the results of a dataflow analysis. use std::cmp::Ordering; +use std::ops::{Deref, DerefMut}; #[cfg(debug_assertions)] use rustc_index::bit_set::BitSet; @@ -8,6 +9,47 @@ use rustc_middle::mir::{self, BasicBlock, Location}; use super::{Analysis, Direction, Effect, EffectIndex, Results}; +/// Some `ResultsCursor`s want to own a `Results`, and some want to borrow a `Results`, either +/// mutable or immutably. This type allows all of the above. It's similar to `Cow`. +pub enum ResultsHandle<'a, 'tcx, A> +where + A: Analysis<'tcx>, +{ + Borrowed(&'a Results<'tcx, A>), + BorrowedMut(&'a mut Results<'tcx, A>), + Owned(Results<'tcx, A>), +} + +impl<'tcx, A> Deref for ResultsHandle<'_, 'tcx, A> +where + A: Analysis<'tcx>, +{ + type Target = Results<'tcx, A>; + + fn deref(&self) -> &Results<'tcx, A> { + match self { + ResultsHandle::Borrowed(borrowed) => borrowed, + ResultsHandle::BorrowedMut(borrowed) => borrowed, + ResultsHandle::Owned(owned) => owned, + } + } +} + +impl<'tcx, A> DerefMut for ResultsHandle<'_, 'tcx, A> +where + A: Analysis<'tcx>, +{ + fn deref_mut(&mut self) -> &mut Results<'tcx, A> { + match self { + ResultsHandle::Borrowed(_borrowed) => { + panic!("tried to deref_mut a `ResultsHandle::Borrowed") + } + ResultsHandle::BorrowedMut(borrowed) => borrowed, + ResultsHandle::Owned(owned) => owned, + } + } +} + /// Allows random access inspection of the results of a dataflow analysis. Use this when you want /// to inspect domain values only in certain locations; use `ResultsVisitor` if you want to inspect /// domain values in many or all locations. @@ -23,7 +65,7 @@ where A: Analysis<'tcx>, { body: &'mir mir::Body<'tcx>, - results: Results<'tcx, A>, + results: ResultsHandle<'mir, 'tcx, A>, state: A::Domain, pos: CursorPosition, @@ -51,13 +93,8 @@ where self.body } - /// Unwraps this cursor, returning the underlying `Results`. - pub fn into_results(self) -> Results<'tcx, A> { - self.results - } - /// Returns a new cursor that can inspect `results`. - pub fn new(body: &'mir mir::Body<'tcx>, results: Results<'tcx, A>) -> Self { + pub fn new(body: &'mir mir::Body<'tcx>, results: ResultsHandle<'mir, 'tcx, A>) -> Self { let bottom_value = results.analysis.bottom_value(body); ResultsCursor { body, diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 98a4f58cb5d..6e4994af8b4 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -47,20 +47,16 @@ where { pub(crate) fn new( body: &'mir Body<'tcx>, - results: Results<'tcx, A>, + results: &'mir Results<'tcx, A>, style: OutputStyle, ) -> Self { let reachable = mir::traversal::reachable_as_bitset(body); - Formatter { cursor: results.into_results_cursor(body).into(), style, reachable } + Formatter { cursor: results.as_results_cursor(body).into(), style, reachable } } fn body(&self) -> &'mir Body<'tcx> { self.cursor.borrow().body() } - - pub(crate) fn into_results(self) -> Results<'tcx, A> { - self.cursor.into_inner().into_results() - } } /// A pair of a basic block and an index into that basic blocks `successors`. diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index f9e7ba743fc..88bab250781 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -302,14 +302,13 @@ pub trait Analysis<'tcx> { let results = Results { analysis: self, entry_sets }; if tcx.sess.opts.unstable_opts.dump_mir_dataflow { - let (res, results) = write_graphviz_results(tcx, body, results, pass_name); + let res = write_graphviz_results(tcx, body, &results, pass_name); if let Err(e) = res { error!("Failed to write graphviz dataflow results: {}", e); } - results - } else { - results } + + results } } diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index 7c775ae7f4a..8493a7aa44b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -17,6 +17,7 @@ use super::{Analysis, ResultsCursor, ResultsVisitor, graphviz, visit_results}; use crate::errors::{ DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, }; +use crate::framework::cursor::ResultsHandle; pub type EntrySets<'tcx, A> = IndexVec>::Domain>; @@ -36,12 +37,30 @@ impl<'tcx, A> Results<'tcx, A> where A: Analysis<'tcx>, { - /// Creates a `ResultsCursor` that can inspect these `Results`. + /// Creates a `ResultsCursor` that can inspect these `Results`. Immutably borrows the `Results`, + /// which is appropriate when the `Results` is used outside the cursor. + pub fn as_results_cursor<'mir>( + &'mir self, + body: &'mir mir::Body<'tcx>, + ) -> ResultsCursor<'mir, 'tcx, A> { + ResultsCursor::new(body, ResultsHandle::Borrowed(self)) + } + + /// Creates a `ResultsCursor` that can mutate these `Results`. Mutably borrows the `Results`, + /// which is appropriate when the `Results` is used outside the cursor. + pub fn as_results_cursor_mut<'mir>( + &'mir mut self, + body: &'mir mir::Body<'tcx>, + ) -> ResultsCursor<'mir, 'tcx, A> { + ResultsCursor::new(body, ResultsHandle::BorrowedMut(self)) + } + + /// Creates a `ResultsCursor` that takes ownership of the `Results`. pub fn into_results_cursor<'mir>( self, body: &'mir mir::Body<'tcx>, ) -> ResultsCursor<'mir, 'tcx, A> { - ResultsCursor::new(body, self) + ResultsCursor::new(body, ResultsHandle::Owned(self)) } /// Gets the dataflow state for the given block. @@ -76,9 +95,9 @@ where pub(super) fn write_graphviz_results<'tcx, A>( tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, - results: Results<'tcx, A>, + results: &Results<'tcx, A>, pass_name: Option<&'static str>, -) -> (std::io::Result<()>, Results<'tcx, A>) +) -> std::io::Result<()> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -89,7 +108,7 @@ where let def_id = body.source.def_id(); let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else { // Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse` - return (Ok(()), results); + return Ok(()); }; let file = try { @@ -106,12 +125,12 @@ where create_dump_file(tcx, "dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)? } - _ => return (Ok(()), results), + _ => return Ok(()), } }; let mut file = match file { Ok(f) => f, - Err(e) => return (Err(e), results), + Err(e) => return Err(e), }; let style = match attrs.formatter { @@ -134,7 +153,7 @@ where file.write_all(&buf)?; }; - (lhs, graphviz.into_results()) + lhs } #[derive(Default)] diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 8295a806d71..ae5506b05e7 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -676,12 +676,11 @@ fn locals_live_across_suspend_points<'tcx>( let mut borrowed_locals_cursor = borrowed_locals_results.clone().into_results_cursor(body); - // Calculate the MIR locals that we actually need to keep storage around - // for. - let mut requires_storage_cursor = + // Calculate the MIR locals that we need to keep storage around for. + let mut requires_storage_results = MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body)) - .iterate_to_fixpoint(tcx, body, None) - .into_results_cursor(body); + .iterate_to_fixpoint(tcx, body, None); + let mut requires_storage_cursor = requires_storage_results.as_results_cursor_mut(body); // Calculate the liveness of MIR locals ignoring borrows. let mut liveness = @@ -754,7 +753,7 @@ fn locals_live_across_suspend_points<'tcx>( body, &saved_locals, always_live_locals.clone(), - requires_storage_cursor.into_results(), + requires_storage_results, ); LivenessInfo { -- cgit 1.4.1-3-g733a5 From 3d12160dfcb4d95cd3f1eaa23071fb9b4e3d69ab Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 22 Nov 2024 17:52:02 +1100 Subject: Move `always_storage_live_locals`. It's very closely related to `MaybeStorageLive` and `MaybeStorageDead`. It's weird that it's currently in a different module. --- compiler/rustc_const_eval/src/check_consts/check.rs | 3 +-- compiler/rustc_const_eval/src/interpret/stack.rs | 2 +- compiler/rustc_mir_dataflow/src/impls/mod.rs | 4 +++- .../rustc_mir_dataflow/src/impls/storage_liveness.rs | 17 +++++++++++++++++ compiler/rustc_mir_dataflow/src/lib.rs | 1 - compiler/rustc_mir_dataflow/src/storage.rs | 20 -------------------- compiler/rustc_mir_transform/src/coroutine.rs | 2 +- compiler/rustc_mir_transform/src/lint.rs | 3 +-- compiler/rustc_mir_transform/src/ref_prop.rs | 3 +-- 9 files changed, 25 insertions(+), 30 deletions(-) delete mode 100644 compiler/rustc_mir_dataflow/src/storage.rs (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 9f21c864487..916929b6c0b 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -18,8 +18,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_mir_dataflow::Analysis; -use rustc_mir_dataflow::impls::MaybeStorageLive; -use rustc_mir_dataflow::storage::always_storage_live_locals; +use rustc_mir_dataflow::impls::{MaybeStorageLive, always_storage_live_locals}; use rustc_span::{Span, Symbol, sym}; use rustc_trait_selection::traits::{ Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt, diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 8ce11c71b8b..a9ebf386617 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -10,7 +10,7 @@ use rustc_index::IndexVec; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; -use rustc_mir_dataflow::storage::always_storage_live_locals; +use rustc_mir_dataflow::impls::always_storage_live_locals; use rustc_span::Span; use tracing::{info_span, instrument, trace}; diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index 9b5bfa9bfa0..5b7866ace46 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -15,4 +15,6 @@ pub use self::initialized::{ pub use self::liveness::{ MaybeLiveLocals, MaybeTransitiveLiveLocals, TransferFunction as LivenessTransferFunction, }; -pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive}; +pub use self::storage_liveness::{ + MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive, always_storage_live_locals, +}; diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 1315d7aab4d..9c18ab43bd9 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -7,6 +7,23 @@ use rustc_middle::mir::*; use super::MaybeBorrowedLocals; use crate::{Analysis, GenKill, ResultsCursor}; +/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations. +/// +/// These locals have fixed storage for the duration of the body. +pub fn always_storage_live_locals(body: &Body<'_>) -> BitSet { + let mut always_live_locals = BitSet::new_filled(body.local_decls.len()); + + for block in &*body.basic_blocks { + for statement in &block.statements { + if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = statement.kind { + always_live_locals.remove(l); + } + } + } + + always_live_locals +} + pub struct MaybeStorageLive<'a> { always_live_locals: Cow<'a, BitSet>, } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 7ef7c541173..e33f65ff774 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -33,7 +33,6 @@ pub mod impls; pub mod move_paths; pub mod points; pub mod rustc_peek; -pub mod storage; pub mod un_derefer; pub mod value_analysis; diff --git a/compiler/rustc_mir_dataflow/src/storage.rs b/compiler/rustc_mir_dataflow/src/storage.rs deleted file mode 100644 index e5a0e1d312e..00000000000 --- a/compiler/rustc_mir_dataflow/src/storage.rs +++ /dev/null @@ -1,20 +0,0 @@ -use rustc_index::bit_set::BitSet; -use rustc_middle::mir::{self, Local}; - -/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations. -/// -/// These locals have fixed storage for the duration of the body. -pub fn always_storage_live_locals(body: &mir::Body<'_>) -> BitSet { - let mut always_live_locals = BitSet::new_filled(body.local_decls.len()); - - for block in &*body.basic_blocks { - for statement in &block.statements { - use mir::StatementKind::{StorageDead, StorageLive}; - if let StorageLive(l) | StorageDead(l) = statement.kind { - always_live_locals.remove(l); - } - } - } - - always_live_locals -} diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 8295a806d71..f262912fab1 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -70,8 +70,8 @@ use rustc_middle::ty::{ use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, + always_storage_live_locals, }; -use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor}; use rustc_span::Span; use rustc_span::def_id::{DefId, LocalDefId}; diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index d8ff1cfc90b..29e762af8de 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -9,8 +9,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive}; -use rustc_mir_dataflow::storage::always_storage_live_locals; +use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive, always_storage_live_locals}; use rustc_mir_dataflow::{Analysis, ResultsCursor}; pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index af438ac2177..96bcdfa6fac 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -8,8 +8,7 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::Analysis; -use rustc_mir_dataflow::impls::MaybeStorageDead; -use rustc_mir_dataflow::storage::always_storage_live_locals; +use rustc_mir_dataflow::impls::{MaybeStorageDead, always_storage_live_locals}; use tracing::{debug, instrument}; use crate::ssa::{SsaLocals, StorageLiveLocals}; -- cgit 1.4.1-3-g733a5 From e3ef2ff05fc8e99f9a187e788713c65486f04d16 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 25 Nov 2024 06:50:55 +1100 Subject: Streamline a `BitSet` creation. --- compiler/rustc_mir_transform/src/coroutine.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index f262912fab1..7fbb5d70d66 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -697,8 +697,7 @@ fn locals_live_across_suspend_points<'tcx>( let loc = Location { block, statement_index: data.statements.len() }; liveness.seek_to_block_end(block); - let mut live_locals: BitSet<_> = BitSet::new_empty(body.local_decls.len()); - live_locals.union(liveness.get()); + let mut live_locals = liveness.get().clone(); if !movable { // The `liveness` variable contains the liveness of MIR locals ignoring borrows. -- cgit 1.4.1-3-g733a5 From 7fa021ad86fb62753576332a1a52b78acac492f9 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 1 May 2023 09:56:39 +0000 Subject: Remove -Zfuel. --- compiler/rustc_driver_impl/src/lib.rs | 4 -- compiler/rustc_interface/src/tests.rs | 2 - compiler/rustc_middle/src/ty/context.rs | 4 -- compiler/rustc_middle/src/ty/mod.rs | 5 +- compiler/rustc_mir_transform/src/dest_prop.rs | 5 -- .../src/early_otherwise_branch.rs | 4 -- compiler/rustc_mir_transform/src/inline.rs | 6 -- compiler/rustc_mir_transform/src/instsimplify.rs | 71 +++++----------------- compiler/rustc_mir_transform/src/match_branches.rs | 5 -- .../src/multiple_return_terminators.rs | 7 +-- compiler/rustc_mir_transform/src/nrvo.rs | 4 -- .../src/remove_unneeded_drops.rs | 5 -- compiler/rustc_mir_transform/src/remove_zsts.rs | 12 +--- .../rustc_mir_transform/src/unreachable_prop.rs | 6 -- compiler/rustc_session/messages.ftl | 2 - compiler/rustc_session/src/config.rs | 8 --- compiler/rustc_session/src/errors.rs | 6 -- compiler/rustc_session/src/options.rs | 20 ------ compiler/rustc_session/src/session.rs | 59 +----------------- tests/ui/fuel/optimization-fuel-0.rs | 17 ------ tests/ui/fuel/optimization-fuel-0.stderr | 4 -- tests/ui/fuel/optimization-fuel-1.rs | 18 ------ tests/ui/fuel/optimization-fuel-1.stderr | 4 -- tests/ui/fuel/print-fuel.rs | 13 ---- tests/ui/fuel/print-fuel.stderr | 1 - tests/ui/lint/issue-79546-fuel-ice.rs | 8 --- 26 files changed, 19 insertions(+), 281 deletions(-) delete mode 100644 tests/ui/fuel/optimization-fuel-0.rs delete mode 100644 tests/ui/fuel/optimization-fuel-0.stderr delete mode 100644 tests/ui/fuel/optimization-fuel-1.rs delete mode 100644 tests/ui/fuel/optimization-fuel-1.stderr delete mode 100644 tests/ui/fuel/print-fuel.rs delete mode 100644 tests/ui/fuel/print-fuel.stderr delete mode 100644 tests/ui/lint/issue-79546-fuel-ice.rs (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c270ce16726..256266d2965 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -472,10 +472,6 @@ fn run_compiler( linker.link(sess, codegen_backend)? } - if let Some(fuel) = sess.opts.unstable_opts.print_fuel.as_deref() { - eprintln!("Fuel used by {}: {}", fuel, sess.print_fuel.load(Ordering::SeqCst)); - } - Ok(()) }) } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index e48c4d46b59..6beae14100d 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -784,7 +784,6 @@ fn test_unstable_options_tracking_hash() { tracked!(flatten_format_args, false); tracked!(fmt_debug, FmtDebug::Shallow); tracked!(force_unstable_if_unmarked, true); - tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_return, FunctionReturn::ThunkExtern); tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); @@ -830,7 +829,6 @@ fn test_unstable_options_tracking_hash() { tracked!(plt, Some(true)); tracked!(polonius, Polonius::Legacy); tracked!(precise_enum_drop_elaboration, false); - tracked!(print_fuel, Some("abc".to_string())); tracked!(profile_sample_use, Some(PathBuf::from("abc"))); tracked!(profiler_runtime, "abc".to_string()); tracked!(regparm, Some(3)); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d982122e2aa..5bf62a17c8e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1566,10 +1566,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn consider_optimizing String>(self, msg: T) -> bool { - self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg) - } - /// Obtain all lang items of this crate and all dependencies (recursively) pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems { self.get_lang_items(()) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2b532701904..c7a2223ecd7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1558,10 +1558,7 @@ impl<'tcx> TyCtxt<'tcx> { let is_box = self.is_lang_item(did.to_def_id(), LangItem::OwnedBox); // This is here instead of layout because the choice must make it into metadata. - if is_box - || !self - .consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) - { + if is_box { flags.insert(ReprFlags::IS_LINEAR); } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 9c74b2f0839..8f977d2979e 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -217,11 +217,6 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { else { continue; }; - if !tcx.consider_optimizing(|| { - format!("{} round {}", tcx.def_path_str(def_id), round_count) - }) { - break; - } // Replace `src` by `dest` everywhere. merges.insert(*src, *dest); diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 704ed508b22..17c8348140a 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -108,10 +108,6 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { let parent = BasicBlock::from_usize(i); let Some(opt_data) = evaluate_candidate(tcx, body, parent) else { continue }; - if !tcx.consider_optimizing(|| format!("EarlyOtherwiseBranch {opt_data:?}")) { - break; - } - trace!("SUCCESS: found optimization possibility to apply: {opt_data:?}"); should_cleanup = true; diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 00f6c3845d4..0878fa26a92 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -210,12 +210,6 @@ impl<'tcx> Inliner<'tcx> { let callee_body = try_instance_mir(self.tcx, callsite.callee.def)?; self.check_mir_body(callsite, callee_body, callee_attrs, cross_crate_inlinable)?; - if !self.tcx.consider_optimizing(|| { - format!("Inline {:?} into {:?}", callsite.callee, caller_body.source) - }) { - return Err("optimization fuel exhausted"); - } - let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions( self.tcx, self.typing_env, diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 3352d583f2c..a6ba2f32d32 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -7,8 +7,8 @@ use rustc_middle::bug; use rustc_middle::mir::*; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout}; -use rustc_span::sym; use rustc_span::symbol::Symbol; +use rustc_span::{DUMMY_SP, sym}; use crate::simplify::simplify_duplicate_switch_targets; use crate::take_array; @@ -43,12 +43,12 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { match statement.kind { StatementKind::Assign(box (_place, ref mut rvalue)) => { if !preserve_ub_checks { - ctx.simplify_ub_check(&statement.source_info, rvalue); + ctx.simplify_ub_check(rvalue); } - ctx.simplify_bool_cmp(&statement.source_info, rvalue); - ctx.simplify_ref_deref(&statement.source_info, rvalue); - ctx.simplify_len(&statement.source_info, rvalue); - ctx.simplify_ptr_aggregate(&statement.source_info, rvalue); + ctx.simplify_bool_cmp(rvalue); + ctx.simplify_ref_deref(rvalue); + ctx.simplify_len(rvalue); + ctx.simplify_ptr_aggregate(rvalue); ctx.simplify_cast(rvalue); } _ => {} @@ -70,23 +70,8 @@ struct InstSimplifyContext<'a, 'tcx> { } impl<'tcx> InstSimplifyContext<'_, 'tcx> { - fn should_simplify(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool { - self.should_simplify_custom(source_info, "Rvalue", rvalue) - } - - fn should_simplify_custom( - &self, - source_info: &SourceInfo, - label: &str, - value: impl std::fmt::Debug, - ) -> bool { - self.tcx.consider_optimizing(|| { - format!("InstSimplify - {label}: {value:?} SourceInfo: {source_info:?}") - }) - } - /// Transform boolean comparisons into logical operations. - fn simplify_bool_cmp(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { + fn simplify_bool_cmp(&self, rvalue: &mut Rvalue<'tcx>) { match rvalue { Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) => { let new = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) { @@ -117,9 +102,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { _ => None, }; - if let Some(new) = new - && self.should_simplify(source_info, rvalue) - { + if let Some(new) = new { *rvalue = new; } } @@ -134,17 +117,13 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } /// Transform `&(*a)` ==> `a`. - fn simplify_ref_deref(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { + fn simplify_ref_deref(&self, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue { if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() { if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty { return; } - if !self.should_simplify(source_info, rvalue) { - return; - } - *rvalue = Rvalue::Use(Operand::Copy(Place { local: base.local, projection: self.tcx.mk_place_elems(base.projection), @@ -154,36 +133,24 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } /// Transform `Len([_; N])` ==> `N`. - fn simplify_len(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { + fn simplify_len(&self, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::Len(ref place) = *rvalue { let place_ty = place.ty(self.local_decls, self.tcx).ty; if let ty::Array(_, len) = *place_ty.kind() { - if !self.should_simplify(source_info, rvalue) { - return; - } - let const_ = Const::from_ty_const(len, self.tcx.types.usize, self.tcx); - let constant = ConstOperand { span: source_info.span, const_, user_ty: None }; + let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None }; *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); } } } /// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`. - fn simplify_ptr_aggregate(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { + fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::Aggregate(box AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue { let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx); if meta_ty.is_unit() { // The mutable borrows we're holding prevent printing `rvalue` here - if !self.should_simplify_custom( - source_info, - "Aggregate::RawPtr", - (&pointee_ty, *mutability, &fields), - ) { - return; - } - let mut fields = std::mem::take(fields); let _meta = fields.pop().unwrap(); let data = fields.pop().unwrap(); @@ -193,10 +160,10 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } } - fn simplify_ub_check(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { + fn simplify_ub_check(&self, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue { let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks()); - let constant = ConstOperand { span: source_info.span, const_, user_ty: None }; + let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None }; *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); } } @@ -284,16 +251,6 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { return; } - if !self.tcx.consider_optimizing(|| { - format!( - "InstSimplify - Call: {:?} SourceInfo: {:?}", - (fn_def_id, fn_args), - terminator.source_info - ) - }) { - return; - } - let Ok([arg]) = take_array(args) else { return }; let Some(arg_place) = arg.node.place() else { return }; diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index ff027680c49..20e2a65b311 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -18,16 +18,11 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let def_id = body.source.def_id(); let typing_env = body.typing_env(tcx); let mut should_cleanup = false; for i in 0..body.basic_blocks.len() { let bbs = &*body.basic_blocks; let bb_idx = BasicBlock::from_usize(i); - if !tcx.consider_optimizing(|| format!("MatchBranchSimplification {def_id:?} ")) { - continue; - } - match bbs[bb_idx].terminator().kind { TerminatorKind::SwitchInt { discr: ref _discr @ (Operand::Copy(_) | Operand::Move(_)), diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index b6d6ef5de1d..a9227524ce5 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -14,10 +14,9 @@ impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators { sess.mir_opt_level() >= 4 } - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // find basic blocks with no statement and a return terminator let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks.len()); - let def_id = body.source.def_id(); let bbs = body.basic_blocks_mut(); for idx in bbs.indices() { if bbs[idx].statements.is_empty() @@ -28,10 +27,6 @@ impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators { } for bb in bbs { - if !tcx.consider_optimizing(|| format!("MultipleReturnTerminators {def_id:?} ")) { - break; - } - if let TerminatorKind::Goto { target } = bb.terminator().kind { if bbs_simple_returns.contains(target) { bb.terminator_mut().kind = TerminatorKind::Return; diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index 98fa149e2bc..cd026ed6806 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -45,10 +45,6 @@ impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace { return; }; - if !tcx.consider_optimizing(|| format!("RenameReturnPlace {def_id:?}")) { - return; - } - debug!( "`{:?}` was eligible for NRVO, making {:?} the return place", def_id, returned_local diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index a535be798cd..e335051d656 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -26,11 +26,6 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { if ty.ty.needs_drop(tcx, typing_env) { continue; } - if !tcx.consider_optimizing(|| { - format!("RemoveUnneededDrops {:?}", body.source.def_id()) - }) { - continue; - } debug!("SUCCESS: replacing `drop` with goto({:?})", target); terminator.kind = TerminatorKind::Goto { target }; should_simplify = true; diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 6fd70fbe9b0..64e183bcbc0 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -17,10 +17,6 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { return; } - if !tcx.consider_optimizing(|| format!("RemoveZsts - {:?}", body.source.def_id())) { - return; - } - let typing_env = body.typing_env(tcx); let local_decls = &body.local_decls; let mut replacer = Replacer { tcx, typing_env, local_decls }; @@ -94,16 +90,12 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { } } - fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) { + fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _: Location) { if let Operand::Constant(_) = operand { return; } let op_ty = operand.ty(self.local_decls, self.tcx); - if self.known_to_be_zst(op_ty) - && self.tcx.consider_optimizing(|| { - format!("RemoveZsts - Operand: {operand:?} Location: {loc:?}") - }) - { + if self.known_to_be_zst(op_ty) { *operand = Operand::Constant(Box::new(self.make_zst(op_ty))) } } diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index 9cd32459c7b..734703ec78b 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -43,12 +43,6 @@ impl crate::MirPass<'_> for UnreachablePropagation { } } - if !tcx - .consider_optimizing(|| format!("UnreachablePropagation {:?} ", body.source.def_id())) - { - return; - } - patch.apply(body); // We do want do keep some unreachable blocks, but make them empty. diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 893c532f1fb..8fd87893a98 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -84,8 +84,6 @@ session_not_supported = not supported session_octal_float_literal_not_supported = octal float literal is not supported -session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg} - session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index d60c56fee75..0124397ea46 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2356,14 +2356,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M early_dcx.early_warn(format!("number of threads was capped at {}", parse::MAX_THREADS_CAP)); } - let fuel = unstable_opts.fuel.is_some() || unstable_opts.print_fuel.is_some(); - if fuel && unstable_opts.threads > 1 { - early_dcx.early_fatal("optimization fuel is incompatible with multiple threads"); - } - if fuel && cg.incremental.is_some() { - early_dcx.early_fatal("optimization fuel is incompatible with incremental compilation"); - } - let incremental = cg.incremental.as_ref().map(PathBuf::from); let assert_incr_state = parse_assert_incr_state(early_dcx, &unstable_opts.assert_incr_state); diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 33f84f10447..736a5ce0704 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -463,12 +463,6 @@ pub fn report_lit_error( } } -#[derive(Diagnostic)] -#[diag(session_optimization_fuel_exhausted)] -pub(crate) struct OptimisationFuelExhausted { - pub(crate) msg: String, -} - #[derive(Diagnostic)] #[diag(session_incompatible_linker_flavor)] #[note] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index edee7b4468c..a2d75917c82 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -394,7 +394,6 @@ mod desc { pub(crate) const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`"; pub(crate) const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub(crate) const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); - pub(crate) const parse_optimization_fuel: &str = "crate=integer"; pub(crate) const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; pub(crate) const parse_instrument_coverage: &str = parse_bool; pub(crate) const parse_coverage_options: &str = @@ -948,21 +947,6 @@ pub mod parse { true } - pub(crate) fn parse_optimization_fuel( - slot: &mut Option<(String, u64)>, - v: Option<&str>, - ) -> bool { - match v { - None => false, - Some(s) => { - let [crate_name, fuel] = *s.split('=').collect::>() else { return false }; - let Ok(fuel) = fuel.parse::() else { return false }; - *slot = Some((crate_name.to_string(), fuel)); - true - } - } - } - pub(crate) fn parse_unpretty(slot: &mut Option, v: Option<&str>) -> bool { match v { None => false, @@ -1794,8 +1778,6 @@ options! { `shallow` prints only type names, `none` prints nothing and disables `{:?}`. (default: `full`)"), force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED], "force all crates to be `rustc_private` unstable (default: no)"), - fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED], - "set the optimization fuel quota for a crate"), function_return: FunctionReturn = (FunctionReturn::default(), parse_function_return, [TRACKED], "replace returns with jumps to `__x86_return_thunk` (default: `keep`)"), function_sections: Option = (None, parse_opt_bool, [TRACKED], @@ -1978,8 +1960,6 @@ options! { #[rustc_lint_opt_deny_field_access("use `Session::print_codegen_stats` instead of this field")] print_codegen_stats: bool = (false, parse_bool, [UNTRACKED], "print codegen statistics (default: no)"), - print_fuel: Option = (None, parse_opt_string, [TRACKED], - "make rustc print the total optimization fuel used by a crate"), print_llvm_passes: bool = (false, parse_bool, [UNTRACKED], "print the LLVM optimization passes being run (default: no)"), print_mono_items: Option = (None, parse_opt_string, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 29fabdd1deb..f585410adb9 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -4,7 +4,6 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::Arc; use std::sync::atomic::AtomicBool; -use std::sync::atomic::Ordering::SeqCst; use std::{env, fmt, io}; use rustc_data_structures::flock; @@ -12,7 +11,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{ - AtomicU64, DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock, + DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock, }; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::codes::*; @@ -49,13 +48,6 @@ use crate::parse::{ParseSess, add_feature_diagnostics}; use crate::search_paths::SearchPath; use crate::{errors, filesearch, lint}; -struct OptimizationFuel { - /// If `-zfuel=crate=n` is specified, initially set to `n`, otherwise `0`. - remaining: u64, - /// We're rejecting all further optimizations. - out_of_fuel: bool, -} - /// The behavior of the CTFE engine when an error occurs with regards to backtraces. #[derive(Clone, Copy)] pub enum CtfeBacktrace { @@ -163,12 +155,6 @@ pub struct Session { /// Data about code being compiled, gathered during compilation. pub code_stats: CodeStats, - /// Tracks fuel info if `-zfuel=crate=n` is specified. - optimization_fuel: Lock, - - /// Always set to zero and incremented so that we can print fuel expended by a crate. - pub print_fuel: AtomicU64, - /// Loaded up early on in the initialization of this `Session` to avoid /// false positives about a job server in our environment. pub jobserver: Client, @@ -532,41 +518,6 @@ impl Session { self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir()) } - /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n. - /// This expends fuel if applicable, and records fuel if applicable. - pub fn consider_optimizing( - &self, - get_crate_name: impl Fn() -> Symbol, - msg: impl Fn() -> String, - ) -> bool { - let mut ret = true; - if let Some((ref c, _)) = self.opts.unstable_opts.fuel { - if c == get_crate_name().as_str() { - assert_eq!(self.threads(), 1); - let mut fuel = self.optimization_fuel.lock(); - ret = fuel.remaining != 0; - if fuel.remaining == 0 && !fuel.out_of_fuel { - if self.dcx().can_emit_warnings() { - // We only call `msg` in case we can actually emit warnings. - // Otherwise, this could cause a `must_produce_diag` ICE - // (issue #79546). - self.dcx().emit_warn(errors::OptimisationFuelExhausted { msg: msg() }); - } - fuel.out_of_fuel = true; - } else if fuel.remaining > 0 { - fuel.remaining -= 1; - } - } - } - if let Some(ref c) = self.opts.unstable_opts.print_fuel { - if c == get_crate_name().as_str() { - assert_eq!(self.threads(), 1); - self.print_fuel.fetch_add(1, SeqCst); - } - } - ret - } - /// Is this edition 2015? pub fn is_rust_2015(&self) -> bool { self.edition().is_rust_2015() @@ -1097,12 +1048,6 @@ pub fn build_session( Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, target_triple)) }; - let optimization_fuel = Lock::new(OptimizationFuel { - remaining: sopts.unstable_opts.fuel.as_ref().map_or(0, |&(_, i)| i), - out_of_fuel: false, - }); - let print_fuel = AtomicU64::new(0); - let prof = SelfProfilerRef::new( self_profiler, sopts.unstable_opts.time_passes.then(|| sopts.unstable_opts.time_passes_format), @@ -1130,8 +1075,6 @@ pub fn build_session( incr_comp_session: RwLock::new(IncrCompSession::NotInitialized), prof, code_stats: Default::default(), - optimization_fuel, - print_fuel, jobserver: jobserver::client(), lint_store: None, registered_lints: false, diff --git a/tests/ui/fuel/optimization-fuel-0.rs b/tests/ui/fuel/optimization-fuel-0.rs deleted file mode 100644 index cbcb1d329a3..00000000000 --- a/tests/ui/fuel/optimization-fuel-0.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ run-pass - -#![crate_name="foo"] - -use std::mem::size_of; - -//@ compile-flags: -Z fuel=foo=0 - -#[allow(dead_code)] -struct S1(u8, u16, u8); -#[allow(dead_code)] -struct S2(u8, u16, u8); - -fn main() { - assert_eq!(size_of::(), 6); - assert_eq!(size_of::(), 6); -} diff --git a/tests/ui/fuel/optimization-fuel-0.stderr b/tests/ui/fuel/optimization-fuel-0.stderr deleted file mode 100644 index f0e2ebfc37a..00000000000 --- a/tests/ui/fuel/optimization-fuel-0.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: optimization-fuel-exhausted: Reorder fields of "S1" - -warning: 1 warning emitted - diff --git a/tests/ui/fuel/optimization-fuel-1.rs b/tests/ui/fuel/optimization-fuel-1.rs deleted file mode 100644 index 97edb0bd259..00000000000 --- a/tests/ui/fuel/optimization-fuel-1.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ run-pass - -#![crate_name="foo"] - -use std::mem::size_of; - -//@ compile-flags: -Z fuel=foo=1 - -#[allow(dead_code)] -struct S1(u8, u16, u8); -#[allow(dead_code)] -struct S2(u8, u16, u8); - -fn main() { - let optimized = (size_of::() == 4) as usize - +(size_of::() == 4) as usize; - assert_eq!(optimized, 1); -} diff --git a/tests/ui/fuel/optimization-fuel-1.stderr b/tests/ui/fuel/optimization-fuel-1.stderr deleted file mode 100644 index 53eafb05830..00000000000 --- a/tests/ui/fuel/optimization-fuel-1.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: optimization-fuel-exhausted: Reorder fields of "S2" - -warning: 1 warning emitted - diff --git a/tests/ui/fuel/print-fuel.rs b/tests/ui/fuel/print-fuel.rs deleted file mode 100644 index fd7e568bea7..00000000000 --- a/tests/ui/fuel/print-fuel.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![crate_name="foo"] -#![allow(dead_code)] - -// (#55495: The --error-format is to sidestep an issue in our test harness) -//@ compile-flags: -C opt-level=0 --error-format human -Z print-fuel=foo -//@ check-pass - -struct S1(u8, u16, u8); -struct S2(u8, u16, u8); -struct S3(u8, u16, u8); - -fn main() { -} diff --git a/tests/ui/fuel/print-fuel.stderr b/tests/ui/fuel/print-fuel.stderr deleted file mode 100644 index cc88cc077bb..00000000000 --- a/tests/ui/fuel/print-fuel.stderr +++ /dev/null @@ -1 +0,0 @@ -Fuel used by foo: 3 diff --git a/tests/ui/lint/issue-79546-fuel-ice.rs b/tests/ui/lint/issue-79546-fuel-ice.rs deleted file mode 100644 index dbee924d26e..00000000000 --- a/tests/ui/lint/issue-79546-fuel-ice.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Regression test for the ICE described in #79546. - -//@ compile-flags: --cap-lints=allow -Zfuel=issue79546=0 -//@ check-pass -#![crate_name="issue79546"] - -struct S; -fn main() {} -- cgit 1.4.1-3-g733a5