summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/mir
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/mir')
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs4
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs129
-rw-r--r--compiler/rustc_middle/src/mir/generic_graph.rs4
-rw-r--r--compiler/rustc_middle/src/mir/generic_graphviz.rs10
-rw-r--r--compiler/rustc_middle/src/mir/graphviz.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs71
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs6
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs14
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs63
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs22
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs29
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs29
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs221
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs79
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs106
-rw-r--r--compiler/rustc_middle/src/mir/query.rs10
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs17
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs22
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs12
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs132
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs29
21 files changed, 556 insertions, 455 deletions
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index 7722e7b47..0ad17e819 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -178,9 +178,7 @@ impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> {
}
}
-TrivialTypeTraversalAndLiftImpls! {
- Cache,
-}
+TrivialTypeTraversalAndLiftImpls! { Cache }
impl<S: Encoder> Encodable<S> for Cache {
#[inline]
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index db24dae11..1efb54bdb 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -6,69 +6,43 @@ use rustc_span::Symbol;
use std::fmt::{self, Debug, Formatter};
rustc_index::newtype_index! {
- /// An ExpressionOperandId value is assigned directly from either a
- /// CounterValueReference.as_u32() (which ascend from 1) or an ExpressionOperandId.as_u32()
- /// (which _*descend*_ from u32::MAX). Id value `0` (zero) represents a virtual counter with a
- /// constant value of `0`.
- #[derive(HashStable)]
- #[max = 0xFFFF_FFFF]
- #[debug_format = "ExpressionOperandId({})"]
- pub struct ExpressionOperandId {
- }
-}
-
-impl ExpressionOperandId {
- /// An expression operand for a "zero counter", as described in the following references:
- ///
- /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter>
- /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#tag>
- /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
+ /// ID of a coverage counter. Values ascend from 0.
///
- /// This operand can be used to count two or more separate code regions with a single counter,
- /// if they run sequentially with no branches, by injecting the `Counter` in a `BasicBlock` for
- /// one of the code regions, and inserting `CounterExpression`s ("add ZERO to the counter") in
- /// the coverage map for the other code regions.
- pub const ZERO: Self = Self::from_u32(0);
-}
-
-rustc_index::newtype_index! {
+ /// Note that LLVM handles counter IDs as `uint32_t`, so there is no need
+ /// to use a larger representation on the Rust side.
#[derive(HashStable)]
#[max = 0xFFFF_FFFF]
- #[debug_format = "CounterValueReference({})"]
- pub struct CounterValueReference {}
+ #[debug_format = "CounterId({})"]
+ pub struct CounterId {}
}
-impl CounterValueReference {
- /// Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO.
- pub const START: Self = Self::from_u32(1);
+impl CounterId {
+ pub const START: Self = Self::from_u32(0);
- /// Returns explicitly-requested zero-based version of the counter id, used
- /// during codegen. LLVM expects zero-based indexes.
- pub fn zero_based_index(self) -> u32 {
- let one_based_index = self.as_u32();
- debug_assert!(one_based_index > 0);
- one_based_index - 1
+ #[inline(always)]
+ pub fn next_id(self) -> Self {
+ Self::from_u32(self.as_u32() + 1)
}
}
rustc_index::newtype_index! {
- /// InjectedExpressionId.as_u32() converts to ExpressionOperandId.as_u32()
+ /// ID of a coverage-counter expression. Values ascend from 0.
///
- /// Values descend from u32::MAX.
+ /// Note that LLVM handles expression IDs as `uint32_t`, so there is no need
+ /// to use a larger representation on the Rust side.
#[derive(HashStable)]
#[max = 0xFFFF_FFFF]
- #[debug_format = "InjectedExpressionId({})"]
- pub struct InjectedExpressionId {}
+ #[debug_format = "ExpressionId({})"]
+ pub struct ExpressionId {}
}
-rustc_index::newtype_index! {
- /// InjectedExpressionIndex.as_u32() translates to u32::MAX - ExpressionOperandId.as_u32()
- ///
- /// Values ascend from 0.
- #[derive(HashStable)]
- #[max = 0xFFFF_FFFF]
- #[debug_format = "InjectedExpressionIndex({})"]
- pub struct InjectedExpressionIndex {}
+impl ExpressionId {
+ pub const START: Self = Self::from_u32(0);
+
+ #[inline(always)]
+ pub fn next_id(self) -> Self {
+ Self::from_u32(self.as_u32() + 1)
+ }
}
rustc_index::newtype_index! {
@@ -81,17 +55,25 @@ rustc_index::newtype_index! {
pub struct MappedExpressionIndex {}
}
-impl From<CounterValueReference> for ExpressionOperandId {
- #[inline]
- fn from(v: CounterValueReference) -> ExpressionOperandId {
- ExpressionOperandId::from(v.as_u32())
- }
+/// Operand of a coverage-counter expression.
+///
+/// Operands can be a constant zero value, an actual coverage counter, or another
+/// expression. Counter/expression operands are referred to by ID.
+#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
+pub enum Operand {
+ Zero,
+ Counter(CounterId),
+ Expression(ExpressionId),
}
-impl From<InjectedExpressionId> for ExpressionOperandId {
- #[inline]
- fn from(v: InjectedExpressionId) -> ExpressionOperandId {
- ExpressionOperandId::from(v.as_u32())
+impl Debug for Operand {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Zero => write!(f, "Zero"),
+ Self::Counter(id) => f.debug_tuple("Counter").field(&id.as_u32()).finish(),
+ Self::Expression(id) => f.debug_tuple("Expression").field(&id.as_u32()).finish(),
+ }
}
}
@@ -99,32 +81,21 @@ impl From<InjectedExpressionId> for ExpressionOperandId {
pub enum CoverageKind {
Counter {
function_source_hash: u64,
- id: CounterValueReference,
+ /// ID of this counter within its enclosing function.
+ /// Expressions in the same function can refer to it as an operand.
+ id: CounterId,
},
Expression {
- id: InjectedExpressionId,
- lhs: ExpressionOperandId,
+ /// ID of this coverage-counter expression within its enclosing function.
+ /// Other expressions in the same function can refer to it as an operand.
+ id: ExpressionId,
+ lhs: Operand,
op: Op,
- rhs: ExpressionOperandId,
+ rhs: Operand,
},
Unreachable,
}
-impl CoverageKind {
- pub fn as_operand_id(&self) -> ExpressionOperandId {
- use CoverageKind::*;
- match *self {
- Counter { id, .. } => ExpressionOperandId::from(id),
- Expression { id, .. } => ExpressionOperandId::from(id),
- Unreachable => bug!("Unreachable coverage cannot be part of an expression"),
- }
- }
-
- pub fn is_expression(&self) -> bool {
- matches!(self, Self::Expression { .. })
- }
-}
-
impl Debug for CoverageKind {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
use CoverageKind::*;
@@ -132,14 +103,14 @@ impl Debug for CoverageKind {
Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()),
Expression { id, lhs, op, rhs } => write!(
fmt,
- "Expression({:?}) = {} {} {}",
+ "Expression({:?}) = {:?} {} {:?}",
id.index(),
- lhs.index(),
+ lhs,
match op {
Op::Add => "+",
Op::Subtract => "-",
},
- rhs.index(),
+ rhs,
),
Unreachable => write!(fmt, "Unreachable"),
}
diff --git a/compiler/rustc_middle/src/mir/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs
index d1f3561c0..d1753427e 100644
--- a/compiler/rustc_middle/src/mir/generic_graph.rs
+++ b/compiler/rustc_middle/src/mir/generic_graph.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::TyCtxt;
pub fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph {
let def_id = body.source.def_id();
let def_name = graphviz_safe_def_name(def_id);
- let graph_name = format!("Mir_{}", def_name);
+ let graph_name = format!("Mir_{def_name}");
let dark_mode = tcx.sess.opts.unstable_opts.graphviz_dark_mode;
// Nodes
@@ -48,7 +48,7 @@ fn bb_to_graph_node(block: BasicBlock, body: &Body<'_>, dark_mode: bool) -> Node
};
let style = NodeStyle { title_bg: Some(bgcolor.to_owned()), ..Default::default() };
- let mut stmts: Vec<String> = data.statements.iter().map(|x| format!("{:?}", x)).collect();
+ let mut stmts: Vec<String> = data.statements.iter().map(|x| format!("{x:?}")).collect();
// add the terminator to the stmts, gsgdt can print it out separately
let mut terminator_head = String::new();
diff --git a/compiler/rustc_middle/src/mir/generic_graphviz.rs b/compiler/rustc_middle/src/mir/generic_graphviz.rs
index ccae7e159..299b50525 100644
--- a/compiler/rustc_middle/src/mir/generic_graphviz.rs
+++ b/compiler/rustc_middle/src/mir/generic_graphviz.rs
@@ -70,8 +70,8 @@ impl<
writeln!(w, r#" graph [{}];"#, graph_attrs.join(" "))?;
let content_attrs_str = content_attrs.join(" ");
- writeln!(w, r#" node [{}];"#, content_attrs_str)?;
- writeln!(w, r#" edge [{}];"#, content_attrs_str)?;
+ writeln!(w, r#" node [{content_attrs_str}];"#)?;
+ writeln!(w, r#" edge [{content_attrs_str}];"#)?;
// Graph label
if let Some(graph_label) = &self.graph_label {
@@ -112,7 +112,7 @@ impl<
// (format!("{:?}", node), color)
// };
let color = if dark_mode { "dimgray" } else { "gray" };
- let (blk, bgcolor) = (format!("{:?}", node), color);
+ let (blk, bgcolor) = (format!("{node:?}"), color);
write!(
w,
r#"<tr><td bgcolor="{bgcolor}" {attrs} colspan="{colspan}">{blk}</td></tr>"#,
@@ -151,7 +151,7 @@ impl<
} else {
"".to_owned()
};
- writeln!(w, r#" {} -> {} [label=<{}>];"#, src, trg, escaped_edge_label)?;
+ writeln!(w, r#" {src} -> {trg} [label=<{escaped_edge_label}>];"#)?;
}
Ok(())
}
@@ -163,7 +163,7 @@ impl<
W: Write,
{
let escaped_label = dot::escape_html(label);
- writeln!(w, r#" label=<<br/><br/>{}<br align="left"/><br/><br/><br/>>;"#, escaped_label)
+ writeln!(w, r#" label=<<br/><br/>{escaped_label}<br align="left"/><br/><br/><br/>>;"#)
}
fn node(&self, node: G::Node) -> String {
diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs
index 2de73db3a..5c7de8644 100644
--- a/compiler/rustc_middle/src/mir/graphviz.rs
+++ b/compiler/rustc_middle/src/mir/graphviz.rs
@@ -127,5 +127,5 @@ fn write_graph_label<'tcx, W: std::fmt::Write>(
}
fn escape<T: Debug>(t: &T) -> String {
- dot::escape_html(&format!("{:?}", t))
+ dot::escape_html(&format!("{t:?}"))
}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index b8030d9db..c787481bf 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -18,9 +18,9 @@ use rustc_span::DUMMY_SP;
use rustc_target::abi::{Align, HasDataLayout, Size};
use super::{
- read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer, Provenance,
- ResourceExhaustionInfo, Scalar, ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess,
- UnsupportedOpInfo,
+ read_target_uint, write_target_uint, AllocId, BadBytesAccess, InterpError, InterpResult,
+ Pointer, PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch,
+ UndefinedBehaviorInfo, UnsupportedOpInfo,
};
use crate::ty;
use init_mask::*;
@@ -173,13 +173,13 @@ pub enum AllocError {
/// A scalar had the wrong size.
ScalarSizeMismatch(ScalarSizeMismatch),
/// Encountered a pointer where we needed raw bytes.
- ReadPointerAsBytes,
+ ReadPointerAsInt(Option<BadBytesAccess>),
/// Partially overwriting a pointer.
- PartialPointerOverwrite(Size),
+ OverwritePartialPointer(Size),
/// Partially copying a pointer.
- PartialPointerCopy(Size),
+ ReadPartialPointer(Size),
/// Using uninitialized data where it is not allowed.
- InvalidUninitBytes(Option<UninitBytesAccess>),
+ InvalidUninitBytes(Option<BadBytesAccess>),
}
pub type AllocResult<T = ()> = Result<T, AllocError>;
@@ -196,12 +196,14 @@ impl AllocError {
ScalarSizeMismatch(s) => {
InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s))
}
- ReadPointerAsBytes => InterpError::Unsupported(UnsupportedOpInfo::ReadPointerAsBytes),
- PartialPointerOverwrite(offset) => InterpError::Unsupported(
- UnsupportedOpInfo::PartialPointerOverwrite(Pointer::new(alloc_id, offset)),
+ ReadPointerAsInt(info) => InterpError::Unsupported(
+ UnsupportedOpInfo::ReadPointerAsInt(info.map(|b| (alloc_id, b))),
),
- PartialPointerCopy(offset) => InterpError::Unsupported(
- UnsupportedOpInfo::PartialPointerCopy(Pointer::new(alloc_id, offset)),
+ OverwritePartialPointer(offset) => InterpError::Unsupported(
+ UnsupportedOpInfo::OverwritePartialPointer(Pointer::new(alloc_id, offset)),
+ ),
+ ReadPartialPointer(offset) => InterpError::Unsupported(
+ UnsupportedOpInfo::ReadPartialPointer(Pointer::new(alloc_id, offset)),
),
InvalidUninitBytes(info) => InterpError::UndefinedBehavior(
UndefinedBehaviorInfo::InvalidUninitBytes(info.map(|b| (alloc_id, b))),
@@ -327,6 +329,9 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
/// Try to create an Allocation of `size` bytes, panics if there is not enough memory
/// available to the compiler to do so.
+ ///
+ /// Example use case: To obtain an Allocation filled with specific data,
+ /// first call this function and then call write_scalar to fill in the right data.
pub fn uninit(size: Size, align: Align) -> Self {
match Self::uninit_inner(size, align, || {
panic!("Allocation::uninit called with panic_on_fail had allocation failure");
@@ -433,14 +438,26 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
range: AllocRange,
) -> AllocResult<&[u8]> {
self.init_mask.is_range_initialized(range).map_err(|uninit_range| {
- AllocError::InvalidUninitBytes(Some(UninitBytesAccess {
+ AllocError::InvalidUninitBytes(Some(BadBytesAccess {
access: range,
- uninit: uninit_range,
+ bad: uninit_range,
}))
})?;
if !Prov::OFFSET_IS_ADDR {
if !self.provenance.range_empty(range, cx) {
- return Err(AllocError::ReadPointerAsBytes);
+ // Find the provenance.
+ let (offset, _prov) = self
+ .provenance
+ .range_get_ptrs(range, cx)
+ .first()
+ .copied()
+ .expect("there must be provenance somewhere here");
+ let start = offset.max(range.start); // the pointer might begin before `range`!
+ let end = (offset + cx.pointer_size()).min(range.end()); // the pointer might end after `range`!
+ return Err(AllocError::ReadPointerAsInt(Some(BadBytesAccess {
+ access: range,
+ bad: AllocRange::from(start..end),
+ })));
}
}
Ok(self.get_bytes_unchecked(range))
@@ -536,23 +553,25 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
// Now use this provenance.
let ptr = Pointer::new(prov, Size::from_bytes(bits));
return Ok(Scalar::from_maybe_pointer(ptr, cx));
+ } else {
+ // Without OFFSET_IS_ADDR, the only remaining case we can handle is total absence of
+ // provenance.
+ if self.provenance.range_empty(range, cx) {
+ return Ok(Scalar::from_uint(bits, range.size));
+ }
+ // Else we have mixed provenance, that doesn't work.
+ return Err(AllocError::ReadPartialPointer(range.start));
}
} else {
// We are *not* reading a pointer.
- // If we can just ignore provenance, do exactly that.
- if Prov::OFFSET_IS_ADDR {
+ // If we can just ignore provenance or there is none, that's easy.
+ if Prov::OFFSET_IS_ADDR || self.provenance.range_empty(range, cx) {
// We just strip provenance.
return Ok(Scalar::from_uint(bits, range.size));
}
+ // There is some provenance and we don't have OFFSET_IS_ADDR. This doesn't work.
+ return Err(AllocError::ReadPointerAsInt(None));
}
-
- // Fallback path for when we cannot treat provenance bytewise or ignore it.
- assert!(!Prov::OFFSET_IS_ADDR);
- if !self.provenance.range_empty(range, cx) {
- return Err(AllocError::ReadPointerAsBytes);
- }
- // There is no provenance, we can just return the bits.
- Ok(Scalar::from_uint(bits, range.size))
}
/// Writes a *non-ZST* scalar.
@@ -571,7 +590,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
assert!(self.mutability == Mutability::Mut);
// `to_bits_or_ptr_internal` is the right method because we just want to store this data
- // as-is into memory.
+ // as-is into memory. This also double-checks that `val.size()` matches `range.size`.
let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? {
Right(ptr) => {
let (provenance, offset) = ptr.into_parts();
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
index d4dd56a42..2c6bb908f 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
@@ -542,11 +542,7 @@ impl InitMaskMaterialized {
debug_assert_eq!(
result,
find_bit_slow(self, start, end, is_init),
- "optimized implementation of find_bit is wrong for start={:?} end={:?} is_init={} init_mask={:#?}",
- start,
- end,
- is_init,
- self
+ "optimized implementation of find_bit is wrong for start={start:?} end={end:?} is_init={is_init} init_mask={self:#?}"
);
result
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index 318f93e12..0243fc451 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -66,7 +66,11 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
/// Returns all ptr-sized provenance in the given range.
/// If the range has length 0, returns provenance that crosses the edge between `start-1` and
/// `start`.
- fn range_get_ptrs(&self, range: AllocRange, cx: &impl HasDataLayout) -> &[(Size, Prov)] {
+ pub(super) fn range_get_ptrs(
+ &self,
+ range: AllocRange,
+ cx: &impl HasDataLayout,
+ ) -> &[(Size, Prov)] {
// We have to go back `pointer_size - 1` bytes, as that one would still overlap with
// the beginning of this range.
let adjusted_start = Size::from_bytes(
@@ -158,7 +162,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
if first < start {
if !Prov::OFFSET_IS_ADDR {
// We can't split up the provenance into less than a pointer.
- return Err(AllocError::PartialPointerOverwrite(first));
+ return Err(AllocError::OverwritePartialPointer(first));
}
// Insert the remaining part in the bytewise provenance.
let prov = self.ptrs[&first];
@@ -171,7 +175,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
let begin_of_last = last - cx.data_layout().pointer_size;
if !Prov::OFFSET_IS_ADDR {
// We can't split up the provenance into less than a pointer.
- return Err(AllocError::PartialPointerOverwrite(begin_of_last));
+ return Err(AllocError::OverwritePartialPointer(begin_of_last));
}
// Insert the remaining part in the bytewise provenance.
let prov = self.ptrs[&begin_of_last];
@@ -246,10 +250,10 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
if !Prov::OFFSET_IS_ADDR {
// There can't be any bytewise provenance, and we cannot split up the begin/end overlap.
if let Some(entry) = begin_overlap {
- return Err(AllocError::PartialPointerCopy(entry.0));
+ return Err(AllocError::ReadPartialPointer(entry.0));
}
if let Some(entry) = end_overlap {
- return Err(AllocError::PartialPointerCopy(entry.0));
+ return Err(AllocError::ReadPartialPointer(entry.0));
}
debug_assert!(self.bytes.is_none());
} else {
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 2435bc59e..e6ef5a41e 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -12,7 +12,8 @@ use rustc_errors::{
use rustc_macros::HashStable;
use rustc_session::CtfeBacktrace;
use rustc_span::def_id::DefId;
-use rustc_target::abi::{call, Align, Size, WrappingRange};
+use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange};
+
use std::borrow::Cow;
use std::{any::Any, backtrace::Backtrace, fmt};
@@ -22,7 +23,7 @@ pub enum ErrorHandled {
/// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
Reported(ReportedErrorInfo),
/// Don't emit an error, the evaluation failed because the MIR was generic
- /// and the substs didn't fully monomorphize it.
+ /// and the args didn't fully monomorphize it.
TooGeneric,
}
@@ -66,9 +67,7 @@ impl Into<ErrorGuaranteed> for ReportedErrorInfo {
}
}
-TrivialTypeTraversalAndLiftImpls! {
- ErrorHandled,
-}
+TrivialTypeTraversalAndLiftImpls! { ErrorHandled }
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
@@ -135,10 +134,6 @@ impl InterpErrorBacktrace {
}
impl<'tcx> InterpErrorInfo<'tcx> {
- pub fn from_parts(kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
- Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
- }
-
pub fn into_parts(self) -> (InterpError<'tcx>, InterpErrorBacktrace) {
let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
(kind, backtrace)
@@ -156,7 +151,7 @@ impl<'tcx> InterpErrorInfo<'tcx> {
}
fn print_backtrace(backtrace: &Backtrace) {
- eprintln!("\n\nAn error occurred in miri:\n{}", backtrace);
+ eprintln!("\n\nAn error occurred in the MIR interpreter:\n{backtrace}");
}
impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
@@ -189,11 +184,8 @@ pub enum InvalidProgramInfo<'tcx> {
/// (which unfortunately typeck does not reject).
/// Not using `FnAbiError` as that contains a nested `LayoutError`.
FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError),
- /// SizeOf of unsized type was requested.
- SizeOfUnsizedType(Ty<'tcx>),
- /// An unsized local was accessed without having been initialized.
- /// This is not meaningful as we can't even have backing memory for such locals.
- UninitUnsizedLocal,
+ /// We are runnning into a nonsense situation due to ConstProp violating our invariants.
+ ConstPropNonsense,
}
/// Details of why a pointer had to be in-bounds.
@@ -228,13 +220,13 @@ impl IntoDiagnosticArg for InvalidMetaKind {
}
}
-/// Details of an access to uninitialized bytes where it is not allowed.
+/// Details of an access to uninitialized bytes / bad pointer bytes where it is not allowed.
#[derive(Debug, Clone, Copy)]
-pub struct UninitBytesAccess {
+pub struct BadBytesAccess {
/// Range of the original memory access.
pub access: AllocRange,
- /// Range of the uninit memory that was encountered. (Might not be maximal.)
- pub uninit: AllocRange,
+ /// Range of the bad memory that was encountered. (Might not be maximal.)
+ pub bad: AllocRange,
}
/// Information about a size mismatch.
@@ -284,8 +276,8 @@ pub enum UndefinedBehaviorInfo<'a> {
InvalidMeta(InvalidMetaKind),
/// Reading a C string that does not end within its allocation.
UnterminatedCString(Pointer),
- /// Dereferencing a dangling pointer after it got freed.
- PointerUseAfterFree(AllocId),
+ /// Using a pointer after it got freed.
+ PointerUseAfterFree(AllocId, CheckInAllocMsg),
/// Used a pointer outside the bounds it is valid for.
/// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.)
PointerOutOfBounds {
@@ -318,15 +310,17 @@ pub enum UndefinedBehaviorInfo<'a> {
/// Using a string that is not valid UTF-8,
InvalidStr(std::str::Utf8Error),
/// Using uninitialized data where it is not allowed.
- InvalidUninitBytes(Option<(AllocId, UninitBytesAccess)>),
+ InvalidUninitBytes(Option<(AllocId, BadBytesAccess)>),
/// Working with a local that is not currently live.
DeadLocal,
/// Data size is not equal to target size.
ScalarSizeMismatch(ScalarSizeMismatch),
/// A discriminant of an uninhabited enum variant is written.
- UninhabitedEnumVariantWritten,
+ UninhabitedEnumVariantWritten(VariantIdx),
+ /// An uninhabited enum variant is projected.
+ UninhabitedEnumVariantRead(VariantIdx),
/// Validation error.
- Validation(ValidationErrorInfo<'a>),
+ ValidationError(ValidationErrorInfo<'a>),
// FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically
// dispatched
/// A custom (free-form) error, created by `err_ub_custom!`.
@@ -368,6 +362,8 @@ pub enum ExpectedKind {
Float,
Int,
FnPtr,
+ EnumTag,
+ Str,
}
impl From<PointerKind> for ExpectedKind {
@@ -381,10 +377,11 @@ impl From<PointerKind> for ExpectedKind {
#[derive(Debug)]
pub enum ValidationErrorKind<'tcx> {
+ PointerAsInt { expected: ExpectedKind },
+ PartialPointer,
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
PtrToStatic { ptr_kind: PointerKind },
PtrToMut { ptr_kind: PointerKind },
- ExpectedNonPtr { value: String },
MutableRefInConst,
NullFnPtr,
NeverVal,
@@ -394,10 +391,8 @@ pub enum ValidationErrorKind<'tcx> {
UnsafeCell,
UninhabitedVal { ty: Ty<'tcx> },
InvalidEnumTag { value: String },
- UninitEnumTag,
- UninitStr,
+ UninhabitedEnumVariant,
Uninit { expected: ExpectedKind },
- UninitVal,
InvalidVTablePtr { value: String },
InvalidMetaSliceTooLarge { ptr_kind: PointerKind },
InvalidMetaTooLarge { ptr_kind: PointerKind },
@@ -425,12 +420,12 @@ pub enum UnsupportedOpInfo {
//
/// Overwriting parts of a pointer; without knowing absolute addresses, the resulting state
/// cannot be represented by the CTFE interpreter.
- PartialPointerOverwrite(Pointer<AllocId>),
- /// Attempting to `copy` parts of a pointer to somewhere else; without knowing absolute
+ OverwritePartialPointer(Pointer<AllocId>),
+ /// Attempting to read or copy parts of a pointer to somewhere else; without knowing absolute
/// addresses, the resulting state cannot be represented by the CTFE interpreter.
- PartialPointerCopy(Pointer<AllocId>),
- /// Encountered a pointer where we needed raw bytes.
- ReadPointerAsBytes,
+ ReadPartialPointer(Pointer<AllocId>),
+ /// Encountered a pointer where we needed an integer.
+ ReadPointerAsInt(Option<(AllocId, BadBytesAccess)>),
/// Accessing thread local statics
ThreadLocalStatic(DefId),
/// Accessing an unsupported extern static.
@@ -496,7 +491,7 @@ impl InterpError<'_> {
matches!(
self,
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
- | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Validation { .. })
+ | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
)
}
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 2d2cfee1b..3543158bf 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -138,15 +138,15 @@ use rustc_target::abi::{AddressSpace, Endian, HasDataLayout};
use crate::mir;
use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::subst::GenericArgKind;
+use crate::ty::GenericArgKind;
use crate::ty::{self, Instance, Ty, TyCtxt};
pub use self::error::{
- struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
- EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind,
- InvalidProgramInfo, MachineStopType, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo,
- ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
- ValidationErrorInfo, ValidationErrorKind,
+ struct_error, BadBytesAccess, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult,
+ EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo,
+ InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType, PointerKind,
+ ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo,
+ UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind,
};
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
@@ -176,7 +176,7 @@ impl<'tcx> GlobalId<'tcx> {
pub fn display(self, tcx: TyCtxt<'tcx>) -> String {
let instance_name = with_no_trimmed_paths!(tcx.def_path_str(self.instance.def.def_id()));
if let Some(promoted) = self.promoted {
- format!("{}::{:?}", instance_name, promoted)
+ format!("{instance_name}::{promoted:?}")
} else {
instance_name
}
@@ -274,7 +274,7 @@ pub struct AllocDecodingState {
// For each `AllocId`, we keep track of which decoding state it's currently in.
decoding_state: Vec<Lock<State>>,
// The offsets of each allocation in the data stream.
- data_offsets: Vec<u32>,
+ data_offsets: Vec<u64>,
}
impl AllocDecodingState {
@@ -289,7 +289,7 @@ impl AllocDecodingState {
AllocDecodingSession { state: self, session_id }
}
- pub fn new(data_offsets: Vec<u32>) -> Self {
+ pub fn new(data_offsets: Vec<u64>) -> Self {
let decoding_state =
std::iter::repeat_with(|| Lock::new(State::Empty)).take(data_offsets.len()).collect();
@@ -559,7 +559,7 @@ impl<'tcx> TyCtxt<'tcx> {
// However, formatting code relies on function identity (see #58320), so we only do
// this for generic functions. Lifetime parameters are ignored.
let is_generic = instance
- .substs
+ .args
.into_iter()
.any(|kind| !matches!(kind.unpack(), GenericArgKind::Lifetime(_)));
if is_generic {
@@ -609,7 +609,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Panics in case the `AllocId` is dangling. Since that is impossible for `AllocId`s in
/// constants (as all constants must pass interning and validation that check for dangling
/// ids), this function is frequently used throughout rustc, but should not be used within
- /// the miri engine.
+ /// the interpreter.
pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> {
match self.try_get_global_alloc(id) {
Some(alloc) => alloc,
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 9c97431f3..fc659ce18 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -2,8 +2,8 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}
use crate::mir;
use crate::query::{TyCtxtAt, TyCtxtEnsure};
-use crate::ty::subst::InternalSubsts;
use crate::ty::visit::TypeVisitableExt;
+use crate::ty::GenericArgs;
use crate::ty::{self, TyCtxt};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
@@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> {
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
// encountered.
- let substs = InternalSubsts::identity_for_item(self, def_id);
- let instance = ty::Instance::new(def_id, substs);
+ 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, None)
@@ -48,14 +48,14 @@ impl<'tcx> TyCtxt<'tcx> {
//
// When trying to evaluate constants containing inference variables,
// use `Infcx::const_eval_resolve` instead.
- if ct.substs.has_non_region_infer() {
+ if ct.args.has_non_region_infer() {
bug!("did not expect inference variables here");
}
match ty::Instance::resolve(
self, param_env,
// FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
- ct.def, ct.substs,
+ ct.def, ct.args,
) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted };
@@ -79,11 +79,11 @@ impl<'tcx> TyCtxt<'tcx> {
//
// When trying to evaluate constants containing inference variables,
// use `Infcx::const_eval_resolve` instead.
- if ct.substs.has_non_region_infer() {
+ if ct.args.has_non_region_infer() {
bug!("did not expect inference variables here");
}
- match ty::Instance::resolve(self, param_env, ct.def, ct.substs) {
+ match ty::Instance::resolve(self, param_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(|_| {
@@ -94,7 +94,7 @@ impl<'tcx> TyCtxt<'tcx> {
// @lcnr believes that successfully evaluating even though there are
// used generic parameters is a bug of evaluation, so checking for it
// here does feel somewhat sensible.
- if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
+ if !self.features().generic_const_exprs && ct.args.has_non_region_param() {
let def_kind = self.def_kind(instance.def_id());
assert!(
matches!(
@@ -139,7 +139,6 @@ impl<'tcx> TyCtxt<'tcx> {
cid: GlobalId<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
- let param_env = param_env.with_const();
// 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.and(cid));
@@ -158,8 +157,6 @@ impl<'tcx> TyCtxt<'tcx> {
cid: GlobalId<'tcx>,
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
- let param_env = param_env.with_const();
- debug!(?param_env);
// 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.and(cid));
@@ -204,7 +201,6 @@ impl<'tcx> TyCtxtAt<'tcx> {
gid: GlobalId<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Result<mir::ConstAllocation<'tcx>, ErrorHandled> {
- let param_env = param_env.with_const();
trace!("eval_to_allocation: Need to compute {:?}", gid);
let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
@@ -221,11 +217,10 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
// encountered.
- let substs = InternalSubsts::identity_for_item(self.tcx, def_id);
- let instance = ty::Instance::new(def_id, substs);
+ let args = GenericArgs::identity_for_item(self.tcx, def_id);
+ let instance = ty::Instance::new(def_id, args);
let cid = GlobalId { instance, promoted: None };
- let param_env =
- self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const();
+ let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx);
// 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));
@@ -238,7 +233,7 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
assert!(self.tcx.is_static(def_id));
let instance = ty::Instance::mono(self.tcx, def_id);
let gid = GlobalId { instance, promoted: None };
- let param_env = ty::ParamEnv::reveal_all().with_const();
+ let param_env = ty::ParamEnv::reveal_all();
trace!("eval_to_allocation: Need to compute {:?}", gid);
self.eval_to_allocation_raw(param_env.and(gid))
}
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 0416411df..5345a6588 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -135,8 +135,8 @@ static_assert_size!(Scalar, 24);
impl<Prov: Provenance> fmt::Debug for Scalar<Prov> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- Scalar::Ptr(ptr, _size) => write!(f, "{:?}", ptr),
- Scalar::Int(int) => write!(f, "{:?}", int),
+ Scalar::Ptr(ptr, _size) => write!(f, "{ptr:?}"),
+ Scalar::Int(int) => write!(f, "{int:?}"),
}
}
}
@@ -144,8 +144,8 @@ impl<Prov: Provenance> fmt::Debug for Scalar<Prov> {
impl<Prov: Provenance> fmt::Display for Scalar<Prov> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
- Scalar::Int(int) => write!(f, "{}", int),
+ Scalar::Ptr(ptr, _size) => write!(f, "pointer to {ptr:?}"),
+ Scalar::Int(int) => write!(f, "{int}"),
}
}
}
@@ -153,8 +153,8 @@ impl<Prov: Provenance> fmt::Display for Scalar<Prov> {
impl<Prov: Provenance> fmt::LowerHex for Scalar<Prov> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
- Scalar::Int(int) => write!(f, "{:#x}", int),
+ Scalar::Ptr(ptr, _size) => write!(f, "pointer to {ptr:?}"),
+ Scalar::Int(int) => write!(f, "{int:#x}"),
}
}
}
@@ -320,6 +320,14 @@ impl<Prov> Scalar<Prov> {
}
})
}
+
+ #[inline]
+ pub fn size(self) -> Size {
+ match self {
+ Scalar::Int(int) => int.size(),
+ Scalar::Ptr(_ptr, sz) => Size::from_bytes(sz),
+ }
+ }
}
impl<'tcx, Prov: Provenance> Scalar<Prov> {
@@ -370,15 +378,16 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
#[inline]
pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
- self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsBytes))?.to_bits(target_size).map_err(
- |size| {
+ self.try_to_int()
+ .map_err(|_| err_unsup!(ReadPointerAsInt(None)))?
+ .to_bits(target_size)
+ .map_err(|size| {
err_ub!(ScalarSizeMismatch(ScalarSizeMismatch {
target_size: target_size.bytes(),
data_size: size.bytes(),
}))
.into()
- },
- )
+ })
}
#[inline(always)]
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 28c505878..9ef3a1b30 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -12,7 +12,7 @@ use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::visit::TypeVisitableExt;
use crate::ty::{self, List, Ty, TyCtxt};
use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
-use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
+use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
use rustc_data_structures::captures::Captures;
use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg};
@@ -619,7 +619,7 @@ impl<D: TyDecoder, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> {
let val = T::decode(d);
ClearCrossCrate::Set(val)
}
- tag => panic!("Invalid tag for ClearCrossCrate: {:?}", tag),
+ tag => panic!("Invalid tag for ClearCrossCrate: {tag:?}"),
}
}
}
@@ -706,9 +706,7 @@ pub enum BindingForm<'tcx> {
RefForGuard,
}
-TrivialTypeTraversalAndLiftImpls! {
- BindingForm<'tcx>,
-}
+TrivialTypeTraversalAndLiftImpls! { BindingForm<'tcx> }
mod binding_form_impl {
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -1048,12 +1046,12 @@ pub enum VarDebugInfoContents<'tcx> {
impl<'tcx> Debug for VarDebugInfoContents<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
match self {
- VarDebugInfoContents::Const(c) => write!(fmt, "{}", c),
- VarDebugInfoContents::Place(p) => write!(fmt, "{:?}", p),
+ VarDebugInfoContents::Const(c) => write!(fmt, "{c}"),
+ VarDebugInfoContents::Place(p) => write!(fmt, "{p:?}"),
VarDebugInfoContents::Composite { ty, fragments } => {
- write!(fmt, "{:?}{{ ", ty)?;
+ write!(fmt, "{ty:?}{{ ")?;
for f in fragments.iter() {
- write!(fmt, "{:?}, ", f)?;
+ write!(fmt, "{f:?}, ")?;
}
write!(fmt, "}}")
}
@@ -1111,10 +1109,6 @@ pub struct VarDebugInfo<'tcx> {
/// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
/// argument number in the original function before it was inlined.
pub argument_index: Option<u16>,
-
- /// The data represents `name` dereferenced `references` times,
- /// and not the direct value.
- pub references: u8,
}
///////////////////////////////////////////////////////////////////////////
@@ -1317,55 +1311,47 @@ impl<O> AssertKind<O> {
match self {
BoundsCheck { ref len, ref index } => write!(
f,
- "\"index out of bounds: the length is {{}} but the index is {{}}\", {:?}, {:?}",
- len, index
+ "\"index out of bounds: the length is {{}} but the index is {{}}\", {len:?}, {index:?}"
),
OverflowNeg(op) => {
- write!(f, "\"attempt to negate `{{}}`, which would overflow\", {:?}", op)
+ write!(f, "\"attempt to negate `{{}}`, which would overflow\", {op:?}")
}
- DivisionByZero(op) => write!(f, "\"attempt to divide `{{}}` by zero\", {:?}", op),
+ DivisionByZero(op) => write!(f, "\"attempt to divide `{{}}` by zero\", {op:?}"),
RemainderByZero(op) => write!(
f,
- "\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {:?}",
- op
+ "\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {op:?}"
),
Overflow(BinOp::Add, l, r) => write!(
f,
- "\"attempt to compute `{{}} + {{}}`, which would overflow\", {:?}, {:?}",
- l, r
+ "\"attempt to compute `{{}} + {{}}`, which would overflow\", {l:?}, {r:?}"
),
Overflow(BinOp::Sub, l, r) => write!(
f,
- "\"attempt to compute `{{}} - {{}}`, which would overflow\", {:?}, {:?}",
- l, r
+ "\"attempt to compute `{{}} - {{}}`, which would overflow\", {l:?}, {r:?}"
),
Overflow(BinOp::Mul, l, r) => write!(
f,
- "\"attempt to compute `{{}} * {{}}`, which would overflow\", {:?}, {:?}",
- l, r
+ "\"attempt to compute `{{}} * {{}}`, which would overflow\", {l:?}, {r:?}"
),
Overflow(BinOp::Div, l, r) => write!(
f,
- "\"attempt to compute `{{}} / {{}}`, which would overflow\", {:?}, {:?}",
- l, r
+ "\"attempt to compute `{{}} / {{}}`, which would overflow\", {l:?}, {r:?}"
),
Overflow(BinOp::Rem, l, r) => write!(
f,
- "\"attempt to compute the remainder of `{{}} % {{}}`, which would overflow\", {:?}, {:?}",
- l, r
+ "\"attempt to compute the remainder of `{{}} % {{}}`, which would overflow\", {l:?}, {r:?}"
),
Overflow(BinOp::Shr, _, r) => {
- write!(f, "\"attempt to shift right by `{{}}`, which would overflow\", {:?}", r)
+ write!(f, "\"attempt to shift right by `{{}}`, which would overflow\", {r:?}")
}
Overflow(BinOp::Shl, _, r) => {
- write!(f, "\"attempt to shift left by `{{}}`, which would overflow\", {:?}", r)
+ write!(f, "\"attempt to shift left by `{{}}`, which would overflow\", {r:?}")
}
MisalignedPointerDereference { required, found } => {
write!(
f,
- "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {:?}, {:?}",
- required, found
+ "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {required:?}, {found:?}"
)
}
_ => write!(f, "\"{}\"", self.description()),
@@ -1461,9 +1447,9 @@ impl Debug for Statement<'_> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
use self::StatementKind::*;
match self.kind {
- Assign(box (ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv),
+ Assign(box (ref place, ref rv)) => write!(fmt, "{place:?} = {rv:?}"),
FakeRead(box (ref cause, ref place)) => {
- write!(fmt, "FakeRead({:?}, {:?})", cause, place)
+ write!(fmt, "FakeRead({cause:?}, {place:?})")
}
Retag(ref kind, ref place) => write!(
fmt,
@@ -1476,20 +1462,20 @@ impl Debug for Statement<'_> {
},
place,
),
- StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
- StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
+ StorageLive(ref place) => write!(fmt, "StorageLive({place:?})"),
+ StorageDead(ref place) => write!(fmt, "StorageDead({place:?})"),
SetDiscriminant { ref place, variant_index } => {
- write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
+ write!(fmt, "discriminant({place:?}) = {variant_index:?}")
}
- Deinit(ref place) => write!(fmt, "Deinit({:?})", place),
+ Deinit(ref place) => write!(fmt, "Deinit({place:?})"),
PlaceMention(ref place) => {
- write!(fmt, "PlaceMention({:?})", place)
+ write!(fmt, "PlaceMention({place:?})")
}
AscribeUserType(box (ref place, ref c_ty), ref variance) => {
- write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
+ write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})")
}
Coverage(box self::Coverage { ref kind, code_region: Some(ref rgn) }) => {
- write!(fmt, "Coverage::{:?} for {:?}", kind, rgn)
+ write!(fmt, "Coverage::{kind:?} for {rgn:?}")
}
Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind),
Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"),
@@ -1602,14 +1588,13 @@ impl<'tcx> Place<'tcx> {
self.projection.iter().any(|elem| elem.is_indirect())
}
- /// If MirPhase >= Derefered and if projection contains Deref,
- /// It's guaranteed to be in the first place
- pub fn has_deref(&self) -> bool {
- // To make sure this is not accidentally used in wrong mir phase
- debug_assert!(
- self.projection.is_empty() || !self.projection[1..].contains(&PlaceElem::Deref)
- );
- self.projection.first() == Some(&PlaceElem::Deref)
+ /// Returns `true` if this `Place`'s first projection is `Deref`.
+ ///
+ /// This is useful because for MIR phases `AnalysisPhase::PostCleanup` and later,
+ /// `Deref` projections can only occur as the first projection. In that case this method
+ /// is equivalent to `is_indirect`, but faster.
+ pub fn is_indirect_first_projection(&self) -> bool {
+ self.as_ref().is_indirect_first_projection()
}
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
@@ -1682,9 +1667,16 @@ impl<'tcx> PlaceRef<'tcx> {
self.projection.iter().any(|elem| elem.is_indirect())
}
- /// If MirPhase >= Derefered and if projection contains Deref,
- /// It's guaranteed to be in the first place
- pub fn has_deref(&self) -> bool {
+ /// Returns `true` if this `Place`'s first projection is `Deref`.
+ ///
+ /// This is useful because for MIR phases `AnalysisPhase::PostCleanup` and later,
+ /// `Deref` projections can only occur as the first projection. In that case this method
+ /// is equivalent to `is_indirect`, but faster.
+ pub fn is_indirect_first_projection(&self) -> bool {
+ // To make sure this is not accidentally used in wrong mir phase
+ debug_assert!(
+ self.projection.is_empty() || !self.projection[1..].contains(&PlaceElem::Deref)
+ );
self.projection.first() == Some(&PlaceElem::Deref)
}
@@ -1769,13 +1761,13 @@ impl Debug for Place<'_> {
for elem in self.projection.iter() {
match elem {
ProjectionElem::OpaqueCast(ty) => {
- write!(fmt, " as {})", ty)?;
+ write!(fmt, " as {ty})")?;
}
ProjectionElem::Downcast(Some(name), _index) => {
- write!(fmt, " as {})", name)?;
+ write!(fmt, " as {name})")?;
}
ProjectionElem::Downcast(None, index) => {
- write!(fmt, " as variant#{:?})", index)?;
+ write!(fmt, " as variant#{index:?})")?;
}
ProjectionElem::Deref => {
write!(fmt, ")")?;
@@ -1784,25 +1776,25 @@ impl Debug for Place<'_> {
write!(fmt, ".{:?}: {:?})", field.index(), ty)?;
}
ProjectionElem::Index(ref index) => {
- write!(fmt, "[{:?}]", index)?;
+ write!(fmt, "[{index:?}]")?;
}
ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => {
- write!(fmt, "[{:?} of {:?}]", offset, min_length)?;
+ write!(fmt, "[{offset:?} of {min_length:?}]")?;
}
ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => {
- write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
+ write!(fmt, "[-{offset:?} of {min_length:?}]")?;
}
ProjectionElem::Subslice { from, to, from_end: true } if to == 0 => {
- write!(fmt, "[{:?}:]", from)?;
+ write!(fmt, "[{from:?}:]")?;
}
ProjectionElem::Subslice { from, to, from_end: true } if from == 0 => {
- write!(fmt, "[:-{:?}]", to)?;
+ write!(fmt, "[:-{to:?}]")?;
}
ProjectionElem::Subslice { from, to, from_end: true } => {
- write!(fmt, "[{:?}:-{:?}]", from, to)?;
+ write!(fmt, "[{from:?}:-{to:?}]")?;
}
ProjectionElem::Subslice { from, to, from_end: false } => {
- write!(fmt, "[{:?}..{:?}]", from, to)?;
+ write!(fmt, "[{from:?}..{to:?}]")?;
}
}
}
@@ -1896,24 +1888,24 @@ impl<'tcx> Debug for Operand<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
use self::Operand::*;
match *self {
- Constant(ref a) => write!(fmt, "{:?}", a),
- Copy(ref place) => write!(fmt, "{:?}", place),
- Move(ref place) => write!(fmt, "move {:?}", place),
+ Constant(ref a) => write!(fmt, "{a:?}"),
+ Copy(ref place) => write!(fmt, "{place:?}"),
+ Move(ref place) => write!(fmt, "move {place:?}"),
}
}
}
impl<'tcx> Operand<'tcx> {
/// Convenience helper to make a constant that refers to the fn
- /// with given `DefId` and substs. Since this is used to synthesize
+ /// with given `DefId` and args. Since this is used to synthesize
/// MIR, assumes `user_ty` is None.
pub fn function_handle(
tcx: TyCtxt<'tcx>,
def_id: DefId,
- substs: impl IntoIterator<Item = GenericArg<'tcx>>,
+ args: impl IntoIterator<Item = GenericArg<'tcx>>,
span: Span,
) -> Self {
- let ty = Ty::new_fn_def(tcx, def_id, substs);
+ let ty = Ty::new_fn_def(tcx, def_id, args);
Operand::Constant(Box::new(Constant {
span,
user_ty: None,
@@ -1937,11 +1929,11 @@ impl<'tcx> Operand<'tcx> {
let param_env_and_ty = ty::ParamEnv::empty().and(ty);
let type_size = tcx
.layout_of(param_env_and_ty)
- .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
+ .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}"))
.size;
let scalar_size = match val {
Scalar::Int(int) => int.size(),
- _ => panic!("Invalid scalar type {:?}", val),
+ _ => panic!("Invalid scalar type {val:?}"),
};
scalar_size == type_size
});
@@ -1981,9 +1973,9 @@ impl<'tcx> Operand<'tcx> {
///
/// While this is unlikely in general, it's the normal case of what you'll
/// find as the `func` in a [`TerminatorKind::Call`].
- pub fn const_fn_def(&self) -> Option<(DefId, SubstsRef<'tcx>)> {
+ pub fn const_fn_def(&self) -> Option<(DefId, GenericArgsRef<'tcx>)> {
let const_ty = self.constant()?.literal.ty();
- if let ty::FnDef(def_id, substs) = *const_ty.kind() { Some((def_id, substs)) } else { None }
+ if let ty::FnDef(def_id, args) = *const_ty.kind() { Some((def_id, args)) } else { None }
}
}
@@ -2057,26 +2049,26 @@ impl<'tcx> Debug for Rvalue<'tcx> {
use self::Rvalue::*;
match *self {
- Use(ref place) => write!(fmt, "{:?}", place),
+ Use(ref place) => write!(fmt, "{place:?}"),
Repeat(ref a, b) => {
- write!(fmt, "[{:?}; ", a)?;
+ write!(fmt, "[{a:?}; ")?;
pretty_print_const(b, fmt, false)?;
write!(fmt, "]")
}
- Len(ref a) => write!(fmt, "Len({:?})", a),
+ Len(ref a) => write!(fmt, "Len({a:?})"),
Cast(ref kind, ref place, ref ty) => {
- write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind)
+ write!(fmt, "{place:?} as {ty:?} ({kind:?})")
}
- BinaryOp(ref op, box (ref a, ref b)) => write!(fmt, "{:?}({:?}, {:?})", op, a, b),
+ BinaryOp(ref op, box (ref a, ref b)) => write!(fmt, "{op:?}({a:?}, {b:?})"),
CheckedBinaryOp(ref op, box (ref a, ref b)) => {
- write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
+ write!(fmt, "Checked{op:?}({a:?}, {b:?})")
}
- UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
- Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
+ UnaryOp(ref op, ref a) => write!(fmt, "{op:?}({a:?})"),
+ Discriminant(ref place) => write!(fmt, "discriminant({place:?})"),
NullaryOp(ref op, ref t) => match op {
- NullOp::SizeOf => write!(fmt, "SizeOf({:?})", t),
- NullOp::AlignOf => write!(fmt, "AlignOf({:?})", t),
- NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({:?}, {:?})", t, fields),
+ NullOp::SizeOf => write!(fmt, "SizeOf({t:?})"),
+ NullOp::AlignOf => write!(fmt, "AlignOf({t:?})"),
+ NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t:?}, {fields:?})"),
},
ThreadLocalRef(did) => ty::tls::with(|tcx| {
let muta = tcx.static_mutability(did).unwrap().prefix_str();
@@ -2103,10 +2095,10 @@ impl<'tcx> Debug for Rvalue<'tcx> {
// Do not even print 'static
String::new()
};
- write!(fmt, "&{}{}{:?}", region, kind_str, place)
+ write!(fmt, "&{region}{kind_str}{place:?}")
}
- CopyForDeref(ref place) => write!(fmt, "deref_copy {:#?}", place),
+ CopyForDeref(ref place) => write!(fmt, "deref_copy {place:#?}"),
AddressOf(mutability, ref place) => {
let kind_str = match mutability {
@@ -2114,7 +2106,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
Mutability::Not => "const",
};
- write!(fmt, "&raw {} {:?}", kind_str, place)
+ write!(fmt, "&raw {kind_str} {place:?}")
}
Aggregate(ref kind, ref places) => {
@@ -2127,7 +2119,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
};
match **kind {
- AggregateKind::Array(_) => write!(fmt, "{:?}", places),
+ AggregateKind::Array(_) => write!(fmt, "{places:?}"),
AggregateKind::Tuple => {
if places.is_empty() {
@@ -2137,12 +2129,12 @@ impl<'tcx> Debug for Rvalue<'tcx> {
}
}
- AggregateKind::Adt(adt_did, variant, substs, _user_ty, _) => {
+ AggregateKind::Adt(adt_did, variant, args, _user_ty, _) => {
ty::tls::with(|tcx| {
let variant_def = &tcx.adt_def(adt_did).variant(variant);
- let substs = tcx.lift(substs).expect("could not lift for printing");
+ let args = tcx.lift(args).expect("could not lift for printing");
let name = FmtPrinter::new(tcx, Namespace::ValueNS)
- .print_def_path(variant_def.def_id, substs)?
+ .print_def_path(variant_def.def_id, args)?
.into_buffer();
match variant_def.ctor_kind() {
@@ -2159,10 +2151,10 @@ impl<'tcx> Debug for Rvalue<'tcx> {
})
}
- AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
+ AggregateKind::Closure(def_id, args) => ty::tls::with(|tcx| {
let name = if tcx.sess.opts.unstable_opts.span_free_formats {
- let substs = tcx.lift(substs).unwrap();
- format!("[closure@{}]", tcx.def_path_str_with_substs(def_id, substs),)
+ let args = tcx.lift(args).unwrap();
+ format!("[closure@{}]", tcx.def_path_str_with_args(def_id, args),)
} else {
let span = tcx.def_span(def_id);
format!(
@@ -2213,7 +2205,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
}
ShallowInitBox(ref place, ref ty) => {
- write!(fmt, "ShallowInitBox({:?}, {:?})", place, ty)
+ write!(fmt, "ShallowInitBox({place:?}, {ty:?})")
}
}
}
@@ -2493,7 +2485,7 @@ impl<'tcx> ConstantKind<'tcx> {
};
debug!("expr.kind: {:?}", expr.kind);
- let ty = tcx.type_of(def).subst_identity();
+ let ty = tcx.type_of(def).instantiate_identity();
debug!(?ty);
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
@@ -2521,23 +2513,22 @@ impl<'tcx> ConstantKind<'tcx> {
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
- let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
+ let parent_args = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
&& let Some(parent_did) = parent_hir_id.as_owner()
{
- InternalSubsts::identity_for_item(tcx, parent_did)
+ GenericArgs::identity_for_item(tcx, parent_did)
} else {
List::empty()
};
- debug!(?parent_substs);
+ debug!(?parent_args);
let did = def.to_def_id();
- let child_substs = InternalSubsts::identity_for_item(tcx, did);
- let substs =
- tcx.mk_substs_from_iter(parent_substs.into_iter().chain(child_substs.into_iter()));
- debug!(?substs);
+ let child_args = GenericArgs::identity_for_item(tcx, did);
+ let args = tcx.mk_args_from_iter(parent_args.into_iter().chain(child_args.into_iter()));
+ debug!(?args);
let span = tcx.def_span(def);
- let uneval = UnevaluatedConst::new(did, substs);
+ let uneval = UnevaluatedConst::new(did, args);
debug!(?span, ?param_env);
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
@@ -2552,7 +2543,7 @@ impl<'tcx> ConstantKind<'tcx> {
Self::Unevaluated(
UnevaluatedConst {
def: did,
- substs: InternalSubsts::identity_for_item(tcx, did),
+ args: GenericArgs::identity_for_item(tcx, did),
promoted: None,
},
ty,
@@ -2578,7 +2569,7 @@ impl<'tcx> ConstantKind<'tcx> {
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct UnevaluatedConst<'tcx> {
pub def: DefId,
- pub substs: SubstsRef<'tcx>,
+ pub args: GenericArgsRef<'tcx>,
pub promoted: Option<Promoted>,
}
@@ -2586,14 +2577,14 @@ impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
assert_eq!(self.promoted, None);
- ty::UnevaluatedConst { def: self.def, substs: self.substs }
+ ty::UnevaluatedConst { def: self.def, args: self.args }
}
}
impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
- pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> {
- UnevaluatedConst { def, substs, promoted: Default::default() }
+ pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> {
+ UnevaluatedConst { def, args, promoted: Default::default() }
}
}
@@ -2758,7 +2749,7 @@ rustc_index::newtype_index! {
impl<'tcx> Debug for Constant<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
- write!(fmt, "{}", self)
+ write!(fmt, "{self}")
}
}
@@ -2834,7 +2825,7 @@ fn pretty_print_const_value<'tcx>(
let ty = tcx.lift(ty).unwrap();
if tcx.sess.verbose() {
- fmt.write_str(&format!("ConstValue({:?}: {})", ct, ty))?;
+ fmt.write_str(&format!("ConstValue({ct:?}: {ty})"))?;
return Ok(());
}
@@ -2904,17 +2895,17 @@ fn pretty_print_const_value<'tcx>(
fmt.write_str(")")?;
}
ty::Adt(def, _) if def.variants().is_empty() => {
- fmt.write_str(&format!("{{unreachable(): {}}}", ty))?;
+ fmt.write_str(&format!("{{unreachable(): {ty}}}"))?;
}
- ty::Adt(def, substs) => {
+ ty::Adt(def, args) => {
let variant_idx = contents
.variant
.expect("destructed mir constant of adt without variant idx");
let variant_def = &def.variant(variant_idx);
- let substs = tcx.lift(substs).unwrap();
+ let args = tcx.lift(args).unwrap();
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
cx.print_alloc_ids = true;
- let cx = cx.print_value_path(variant_def.def_id, substs)?;
+ let cx = cx.print_value_path(variant_def.def_id, args)?;
fmt.write_str(&cx.into_buffer())?;
match variant_def.ctor_kind() {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index ca735d523..8fd980d5a 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -1,5 +1,5 @@
use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
-use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
+use crate::ty::{GenericArgs, Instance, InstanceDef, SymbolName, TyCtxt};
use rustc_attr::InlineAttr;
use rustc_data_structures::base_n;
use rustc_data_structures::fingerprint::Fingerprint;
@@ -56,22 +56,31 @@ impl<'tcx> MonoItem<'tcx> {
}
}
+ // Note: if you change how item size estimates work, you might need to
+ // change NON_INCR_MIN_CGU_SIZE as well.
pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
match *self {
MonoItem::Fn(instance) => {
- // Estimate the size of a function based on how many statements
- // it contains.
- tcx.instance_def_size_estimate(instance.def)
+ match instance.def {
+ // "Normal" functions size estimate: the number of
+ // statements, plus one for the terminator.
+ InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
+ let mir = tcx.instance_mir(instance.def);
+ mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
+ }
+ // Other compiler-generated shims size estimate: 1
+ _ => 1,
+ }
}
- // Conservatively estimate the size of a static declaration
- // or assembly to be 1.
+ // Conservatively estimate the size of a static declaration or
+ // assembly item to be 1.
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
}
}
pub fn is_generic_fn(&self) -> bool {
match *self {
- MonoItem::Fn(ref instance) => instance.substs.non_erasable_generics().next().is_some(),
+ MonoItem::Fn(ref instance) => instance.args.non_erasable_generics().next().is_some(),
MonoItem::Static(..) | MonoItem::GlobalAsm(..) => false,
}
}
@@ -168,14 +177,14 @@ impl<'tcx> MonoItem<'tcx> {
/// which will never be accessed) in its place.
pub fn is_instantiable(&self, tcx: TyCtxt<'tcx>) -> bool {
debug!("is_instantiable({:?})", self);
- let (def_id, substs) = match *self {
- MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
- MonoItem::Static(def_id) => (def_id, InternalSubsts::empty()),
+ let (def_id, args) = match *self {
+ MonoItem::Fn(ref instance) => (instance.def_id(), instance.args),
+ MonoItem::Static(def_id) => (def_id, GenericArgs::empty()),
// global asm never has predicates
MonoItem::GlobalAsm(..) => return true,
};
- !tcx.subst_and_check_impossible_predicates((def_id, &substs))
+ !tcx.subst_and_check_impossible_predicates((def_id, &args))
}
pub fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option<Span> {
@@ -214,9 +223,9 @@ impl<'tcx> MonoItem<'tcx> {
impl<'tcx> fmt::Display for MonoItem<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- MonoItem::Fn(instance) => write!(f, "fn {}", instance),
+ MonoItem::Fn(instance) => write!(f, "fn {instance}"),
MonoItem::Static(def_id) => {
- write!(f, "static {}", Instance::new(def_id, InternalSubsts::empty()))
+ write!(f, "static {}", Instance::new(def_id, GenericArgs::empty()))
}
MonoItem::GlobalAsm(..) => write!(f, "global_asm"),
}
@@ -230,7 +239,7 @@ pub struct CodegenUnit<'tcx> {
/// contain something unique to this crate (e.g., a module path)
/// as well as the crate name and disambiguator.
name: Symbol,
- items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>,
+ items: FxHashMap<MonoItem<'tcx>, MonoItemData>,
size_estimate: usize,
primary: bool,
/// True if this is CGU is used to hold code coverage information for dead code,
@@ -238,6 +247,20 @@ pub struct CodegenUnit<'tcx> {
is_code_coverage_dead_code_cgu: bool,
}
+/// Auxiliary info about a `MonoItem`.
+#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
+pub struct MonoItemData {
+ /// A cached copy of the result of `MonoItem::instantiation_mode`, where
+ /// `GloballyShared` maps to `false` and `LocalCopy` maps to `true`.
+ pub inlined: bool,
+
+ pub linkage: Linkage,
+ pub visibility: Visibility,
+
+ /// A cached copy of the result of `MonoItem::size_estimate`.
+ pub size_estimate: usize,
+}
+
/// Specifies the linkage type for a `MonoItem`.
///
/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants.
@@ -292,12 +315,12 @@ impl<'tcx> CodegenUnit<'tcx> {
}
/// The order of these items is non-determinstic.
- pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
+ pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, MonoItemData> {
&self.items
}
/// The order of these items is non-determinstic.
- pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
+ pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, MonoItemData> {
&mut self.items
}
@@ -320,16 +343,16 @@ impl<'tcx> CodegenUnit<'tcx> {
base_n::encode(hash, base_n::CASE_INSENSITIVE)
}
- pub fn compute_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
- // Estimate the size of a codegen unit as (approximately) the number of MIR
- // statements it corresponds to.
- self.size_estimate = self.items.keys().map(|mi| mi.size_estimate(tcx)).sum();
+ pub fn compute_size_estimate(&mut self) {
+ // The size of a codegen unit as the sum of the sizes of the items
+ // within it.
+ self.size_estimate = self.items.values().map(|data| data.size_estimate).sum();
}
- #[inline]
/// Should only be called if [`compute_size_estimate`] has previously been called.
///
/// [`compute_size_estimate`]: Self::compute_size_estimate
+ #[inline]
pub fn size_estimate(&self) -> usize {
// Items are never zero-sized, so if we have items the estimate must be
// non-zero, unless we forgot to call `compute_size_estimate` first.
@@ -355,7 +378,7 @@ impl<'tcx> CodegenUnit<'tcx> {
pub fn items_in_deterministic_order(
&self,
tcx: TyCtxt<'tcx>,
- ) -> Vec<(MonoItem<'tcx>, (Linkage, Visibility))> {
+ ) -> Vec<(MonoItem<'tcx>, MonoItemData)> {
// The codegen tests rely on items being process in the same order as
// they appear in the file, so for local items, we sort by node_id first
#[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -390,7 +413,7 @@ impl<'tcx> CodegenUnit<'tcx> {
)
}
- let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
+ let mut items: Vec<_> = self.items().iter().map(|(&i, &data)| (i, data)).collect();
items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i));
items
}
@@ -501,27 +524,27 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
// local crate's ID. Otherwise there can be collisions between CGUs
// instantiating stuff for upstream crates.
let local_crate_id = if cnum != LOCAL_CRATE {
- let local_stable_crate_id = tcx.sess.local_stable_crate_id();
+ let local_stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
format!("-in-{}.{:08x}", tcx.crate_name(LOCAL_CRATE), local_stable_crate_id)
} else {
String::new()
};
- let stable_crate_id = tcx.sess.local_stable_crate_id();
+ let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
format!("{}.{:08x}{}", tcx.crate_name(cnum), stable_crate_id, local_crate_id)
});
- write!(cgu_name, "{}", crate_prefix).unwrap();
+ write!(cgu_name, "{crate_prefix}").unwrap();
// Add the components
for component in components {
- write!(cgu_name, "-{}", component).unwrap();
+ write!(cgu_name, "-{component}").unwrap();
}
if let Some(special_suffix) = special_suffix {
// We add a dot in here so it cannot clash with anything in a regular
// Rust identifier
- write!(cgu_name, ".{}", special_suffix).unwrap();
+ write!(cgu_name, ".{special_suffix}").unwrap();
}
Symbol::intern(&cgu_name)
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index ffa7a5400..773056e8a 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -124,14 +124,14 @@ fn dump_matched_mir_node<'tcx, F>(
let def_path =
ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id()));
// ignore-tidy-odd-backticks the literal below is fine
- write!(file, "// MIR for `{}", def_path)?;
+ write!(file, "// MIR for `{def_path}")?;
match body.source.promoted {
None => write!(file, "`")?,
- Some(promoted) => write!(file, "::{:?}`", promoted)?,
+ Some(promoted) => write!(file, "::{promoted:?}`")?,
}
- writeln!(file, " {} {}", disambiguator, pass_name)?;
+ writeln!(file, " {disambiguator} {pass_name}")?;
if let Some(ref layout) = body.generator_layout() {
- writeln!(file, "/* generator_layout = {:#?} */", layout)?;
+ writeln!(file, "/* generator_layout = {layout:#?} */")?;
}
writeln!(file)?;
extra_data(PassWhere::BeforeCFG, &mut file)?;
@@ -169,7 +169,7 @@ fn dump_file_basename<'tcx>(
) -> String {
let source = body.source;
let promotion_id = match source.promoted {
- Some(id) => format!("-{:?}", id),
+ Some(id) => format!("-{id:?}"),
None => String::new(),
};
@@ -203,8 +203,7 @@ fn dump_file_basename<'tcx>(
};
format!(
- "{}.{}{}{}{}.{}.{}",
- crate_name, item_name, shim_disambiguator, promotion_id, pass_num, pass_name, disambiguator,
+ "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}",
)
}
@@ -215,7 +214,7 @@ fn dump_path(tcx: TyCtxt<'_>, basename: &str, extension: &str) -> PathBuf {
let mut file_path = PathBuf::new();
file_path.push(Path::new(&tcx.sess.opts.unstable_opts.dump_mir_dir));
- let file_name = format!("{}.{}", basename, extension,);
+ let file_name = format!("{basename}.{extension}",);
file_path.push(&file_name);
@@ -233,12 +232,12 @@ fn create_dump_file_with_basename(
fs::create_dir_all(parent).map_err(|e| {
io::Error::new(
e.kind(),
- format!("IO error creating MIR dump directory: {:?}; {}", parent, e),
+ format!("IO error creating MIR dump directory: {parent:?}; {e}"),
)
})?;
}
Ok(io::BufWriter::new(fs::File::create(&file_path).map_err(|e| {
- io::Error::new(e.kind(), format!("IO error creating MIR dump file: {:?}; {}", file_path, e))
+ io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}"))
})?))
}
@@ -346,28 +345,24 @@ where
// Basic block label at the top.
let cleanup_text = if data.is_cleanup { " (cleanup)" } else { "" };
- writeln!(w, "{}{:?}{}: {{", INDENT, block, cleanup_text)?;
+ writeln!(w, "{INDENT}{block:?}{cleanup_text}: {{")?;
// List of statements in the middle.
let mut current_location = Location { block, statement_index: 0 };
for statement in &data.statements {
extra_data(PassWhere::BeforeLocation(current_location), w)?;
- let indented_body = format!("{0}{0}{1:?};", INDENT, statement);
+ let indented_body = format!("{INDENT}{INDENT}{statement:?};");
if tcx.sess.opts.unstable_opts.mir_include_spans {
writeln!(
w,
"{:A$} // {}{}",
indented_body,
- if tcx.sess.verbose() {
- format!("{:?}: ", current_location)
- } else {
- String::new()
- },
+ if tcx.sess.verbose() { format!("{current_location:?}: ") } else { String::new() },
comment(tcx, statement.source_info),
A = ALIGN,
)?;
} else {
- writeln!(w, "{}", indented_body)?;
+ writeln!(w, "{indented_body}")?;
}
write_extra(tcx, w, |visitor| {
@@ -387,12 +382,12 @@ where
w,
"{:A$} // {}{}",
indented_terminator,
- if tcx.sess.verbose() { format!("{:?}: ", current_location) } else { String::new() },
+ if tcx.sess.verbose() { format!("{current_location:?}: ") } else { String::new() },
comment(tcx, data.terminator().source_info),
A = ALIGN,
)?;
} else {
- writeln!(w, "{}", indented_terminator)?;
+ writeln!(w, "{indented_terminator}")?;
}
write_extra(tcx, w, |visitor| {
@@ -402,7 +397,7 @@ where
extra_data(PassWhere::AfterLocation(current_location), w)?;
extra_data(PassWhere::AfterTerminator(block), w)?;
- writeln!(w, "{}}}", INDENT)
+ writeln!(w, "{INDENT}}}")
}
/// After we print the main statement, we sometimes dump extra
@@ -457,27 +452,27 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
self.tcx.sess.source_map().span_to_embeddable_string(*span)
));
if let Some(user_ty) = user_ty {
- self.push(&format!("+ user_ty: {:?}", user_ty));
+ self.push(&format!("+ user_ty: {user_ty:?}"));
}
// FIXME: this is a poor version of `pretty_print_const_value`.
let fmt_val = |val: &ConstValue<'tcx>| match val {
ConstValue::ZeroSized => "<ZST>".to_string(),
- ConstValue::Scalar(s) => format!("Scalar({:?})", s),
+ ConstValue::Scalar(s) => format!("Scalar({s:?})"),
ConstValue::Slice { .. } => "Slice(..)".to_string(),
ConstValue::ByRef { .. } => "ByRef(..)".to_string(),
};
let fmt_valtree = |valtree: &ty::ValTree<'tcx>| match valtree {
- ty::ValTree::Leaf(leaf) => format!("ValTree::Leaf({:?})", leaf),
+ ty::ValTree::Leaf(leaf) => format!("ValTree::Leaf({leaf:?})"),
ty::ValTree::Branch(_) => "ValTree::Branch(..)".to_string(),
};
let val = match literal {
ConstantKind::Ty(ct) => match ct.kind() {
- ty::ConstKind::Param(p) => format!("Param({})", p),
+ ty::ConstKind::Param(p) => format!("Param({p})"),
ty::ConstKind::Unevaluated(uv) => {
- format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.substs,)
+ format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
}
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
ty::ConstKind::Error(_) => "Error".to_string(),
@@ -491,7 +486,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
format!(
"Unevaluated({}, {:?}, {:?})",
self.tcx.def_path_str(uv.def),
- uv.substs,
+ uv.args,
uv.promoted,
)
}
@@ -512,22 +507,22 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
self.super_rvalue(rvalue, location);
if let Rvalue::Aggregate(kind, _) = rvalue {
match **kind {
- AggregateKind::Closure(def_id, substs) => {
+ AggregateKind::Closure(def_id, args) => {
self.push("closure");
- self.push(&format!("+ def_id: {:?}", def_id));
- self.push(&format!("+ substs: {:#?}", substs));
+ self.push(&format!("+ def_id: {def_id:?}"));
+ self.push(&format!("+ args: {args:#?}"));
}
- AggregateKind::Generator(def_id, substs, movability) => {
+ AggregateKind::Generator(def_id, args, movability) => {
self.push("generator");
- self.push(&format!("+ def_id: {:?}", def_id));
- self.push(&format!("+ substs: {:#?}", substs));
- self.push(&format!("+ movability: {:?}", movability));
+ self.push(&format!("+ def_id: {def_id:?}"));
+ self.push(&format!("+ args: {args:#?}"));
+ self.push(&format!("+ movability: {movability:?}"));
}
AggregateKind::Adt(_, _, _, Some(user_ty), _) => {
self.push("adt");
- self.push(&format!("+ user_ty: {:?}", user_ty));
+ self.push(&format!("+ user_ty: {user_ty:?}"));
}
_ => {}
@@ -560,13 +555,8 @@ fn write_scope_tree(
}
let indented_debug_info = format!(
- "{0:1$}debug {2} => {3:&<4$}{5:?};",
- INDENT,
- indent,
- var_debug_info.name,
- "",
- var_debug_info.references as usize,
- var_debug_info.value,
+ "{0:1$}debug {2} => {3:?};",
+ INDENT, indent, var_debug_info.name, var_debug_info.value,
);
if tcx.sess.opts.unstable_opts.mir_include_spans {
@@ -578,7 +568,7 @@ fn write_scope_tree(
comment(tcx, var_debug_info.source_info),
)?;
} else {
- writeln!(w, "{}", indented_debug_info)?;
+ writeln!(w, "{indented_debug_info}")?;
}
}
@@ -600,7 +590,7 @@ fn write_scope_tree(
format!("{0:1$}let {2}{3:?}: {4:?}", INDENT, indent, mut_str, local, local_decl.ty);
if let Some(user_ty) = &local_decl.user_ty {
for user_ty in user_ty.projections() {
- write!(indented_decl, " as {:?}", user_ty).unwrap();
+ write!(indented_decl, " as {user_ty:?}").unwrap();
}
}
indented_decl.push(';');
@@ -617,7 +607,7 @@ fn write_scope_tree(
comment(tcx, local_decl.source_info),
)?;
} else {
- writeln!(w, "{}", indented_decl,)?;
+ writeln!(w, "{indented_decl}",)?;
}
}
@@ -654,10 +644,10 @@ fn write_scope_tree(
tcx.sess.source_map().span_to_embeddable_string(span),
)?;
} else {
- writeln!(w, "{}", indented_header)?;
+ writeln!(w, "{indented_header}")?;
}
} else {
- writeln!(w, "{}", indented_header)?;
+ writeln!(w, "{indented_header}")?;
}
write_scope_tree(tcx, body, scope_tree, w, child, depth + 1)?;
@@ -844,7 +834,7 @@ fn write_allocation_endline(w: &mut dyn std::fmt::Write, ascii: &str) -> std::fm
for _ in 0..(BYTES_PER_LINE - ascii.chars().count()) {
write!(w, " ")?;
}
- writeln!(w, " │ {}", ascii)
+ writeln!(w, " │ {ascii}")
}
/// Number of bytes to print per allocation hex dump line.
@@ -880,7 +870,7 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
if num_lines > 0 {
write!(w, "{}0x{:02$x} │ ", prefix, 0, pos_width)?;
} else {
- write!(w, "{}", prefix)?;
+ write!(w, "{prefix}")?;
}
let mut i = Size::ZERO;
@@ -913,10 +903,10 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
let offset = Size::from_bytes(offset);
let provenance_width = |bytes| bytes * 3;
let ptr = Pointer::new(prov, offset);
- let mut target = format!("{:?}", ptr);
+ let mut target = format!("{ptr:?}");
if target.len() > provenance_width(ptr_size.bytes_usize() - 1) {
// This is too long, try to save some space.
- target = format!("{:#?}", ptr);
+ target = format!("{ptr:#?}");
}
if ((i - line_start) + ptr_size).bytes_usize() > BYTES_PER_LINE {
// This branch handles the situation where a provenance starts in the current line
@@ -935,10 +925,10 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
line_start =
write_allocation_newline(w, line_start, &ascii, pos_width, prefix)?;
ascii.clear();
- write!(w, "{0:─^1$}╼", target, overflow_width)?;
+ write!(w, "{target:─^overflow_width$}╼")?;
} else {
oversized_ptr(&mut target, remainder_width);
- write!(w, "╾{0:─^1$}", target, remainder_width)?;
+ write!(w, "╾{target:─^remainder_width$}")?;
line_start =
write_allocation_newline(w, line_start, &ascii, pos_width, prefix)?;
write!(w, "{0:─^1$}╼", "", overflow_width)?;
@@ -955,7 +945,7 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
let provenance_width = provenance_width(ptr_size.bytes_usize() - 1);
oversized_ptr(&mut target, provenance_width);
ascii.push('╾');
- write!(w, "╾{0:─^1$}╼", target, provenance_width)?;
+ write!(w, "╾{target:─^provenance_width$}╼")?;
for _ in 0..ptr_size.bytes() - 2 {
ascii.push('─');
}
@@ -972,7 +962,7 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
// Format is similar to "oversized" above.
let j = i.bytes_usize();
let c = alloc.inspect_with_uninit_and_ptr_outside_interpreter(j..j + 1)[0];
- write!(w, "╾{:02x}{:#?} (1 ptr byte)╼", c, prov)?;
+ write!(w, "╾{c:02x}{prov:#?} (1 ptr byte)╼")?;
i += Size::from_bytes(1);
} else if alloc
.init_mask()
@@ -984,7 +974,7 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
// Checked definedness (and thus range) and provenance. This access also doesn't
// influence interpreter execution but is only for debugging.
let c = alloc.inspect_with_uninit_and_ptr_outside_interpreter(j..j + 1)[0];
- write!(w, "{:02x}", c)?;
+ write!(w, "{c:02x}")?;
if c.is_ascii_control() || c >= 0x80 {
ascii.push('.');
} else {
@@ -1018,7 +1008,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res
_ => tcx.is_closure(def_id),
};
match (kind, body.source.promoted) {
- (_, Some(i)) => write!(w, "{:?} in ", i)?,
+ (_, Some(i)) => write!(w, "{i:?} in ")?,
(DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
(DefKind::Static(hir::Mutability::Not), _) => write!(w, "static ")?,
(DefKind::Static(hir::Mutability::Mut), _) => write!(w, "static mut ")?,
@@ -1051,7 +1041,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res
if let Some(yield_ty) = body.yield_ty() {
writeln!(w)?;
- writeln!(w, "yields {}", yield_ty)?;
+ writeln!(w, "yields {yield_ty}")?;
}
write!(w, " ")?;
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 613b132ff..71bec49af 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -194,11 +194,11 @@ impl Debug for GeneratorLayout<'_> {
}
impl Debug for GenVariantPrinter {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- let variant_name = ty::GeneratorSubsts::variant_name(self.0);
+ let variant_name = ty::GeneratorArgs::variant_name(self.0);
if fmt.alternate() {
write!(fmt, "{:9}({:?})", variant_name, self.0)
} else {
- write!(fmt, "{}", variant_name)
+ write!(fmt, "{variant_name}")
}
}
}
@@ -265,10 +265,10 @@ pub struct ConstQualifs {
/// `UniversalRegions::closure_mapping`.) Note the free regions in the
/// closure's signature and captures are erased.
///
-/// Example: If type check produces a closure with the closure substs:
+/// Example: If type check produces a closure with the closure args:
///
/// ```text
-/// ClosureSubsts = [
+/// ClosureArgs = [
/// 'a, // From the parent.
/// 'b,
/// i8, // the "closure kind"
@@ -280,7 +280,7 @@ pub struct ConstQualifs {
/// We would "renumber" each free region to a unique vid, as follows:
///
/// ```text
-/// ClosureSubsts = [
+/// ClosureArgs = [
/// '1, // From the parent.
/// '2,
/// i8, // the "closure kind"
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 730c55157..20a9e6889 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -159,10 +159,10 @@ where
indent_to_initial_start_col,
source_map.span_to_snippet(spanview_span).expect("function should have printable source")
);
- writeln!(w, "{}", HEADER)?;
- writeln!(w, "<title>{}</title>", title)?;
- writeln!(w, "{}", STYLE_SECTION)?;
- writeln!(w, "{}", START_BODY)?;
+ writeln!(w, "{HEADER}")?;
+ writeln!(w, "<title>{title}</title>")?;
+ writeln!(w, "{STYLE_SECTION}")?;
+ writeln!(w, "{START_BODY}")?;
write!(
w,
r#"<div class="code" style="counter-reset: line {}"><span class="line">{}"#,
@@ -226,7 +226,7 @@ where
write_coverage_gap(tcx, from_pos, end_pos, w)?;
}
writeln!(w, r#"</span></div>"#)?;
- writeln!(w, "{}", FOOTER)?;
+ writeln!(w, "{FOOTER}")?;
Ok(())
}
@@ -561,17 +561,16 @@ where
}
for (i, line) in html_snippet.lines().enumerate() {
if i > 0 {
- write!(w, "{}", NEW_LINE_SPAN)?;
+ write!(w, "{NEW_LINE_SPAN}")?;
}
write!(
w,
- r#"<span class="code{}" style="--layer: {}"{}>{}</span>"#,
- maybe_alt_class, layer, maybe_title_attr, line
+ r#"<span class="code{maybe_alt_class}" style="--layer: {layer}"{maybe_title_attr}>{line}</span>"#
)?;
}
// Check for and translate trailing newlines, because `str::lines()` ignores them
if html_snippet.ends_with('\n') {
- write!(w, "{}", NEW_LINE_SPAN)?;
+ write!(w, "{NEW_LINE_SPAN}")?;
}
if layer == 1 {
write!(w, "</span>")?;
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 7f1d38203..be27bf75d 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -8,7 +8,7 @@ use super::{BasicBlock, Constant, Local, SwitchTargets, UserTypeProjection};
use crate::mir::coverage::{CodeRegion, CoverageKind};
use crate::traits::Reveal;
use crate::ty::adjustment::PointerCoercion;
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
use crate::ty::{self, List, Ty};
use crate::ty::{Region, UserTypeAnnotationIndex};
@@ -1050,10 +1050,6 @@ pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
/// there may be other effects: if the type has a validity constraint loading the place might be UB
/// if the validity constraint is not met.
///
-/// **Needs clarification:** Ralf proposes that loading a place not have side-effects.
-/// This is what is implemented in miri today. Are these the semantics we want for MIR? Is this
-/// something we can even decide without knowing more about Rust's memory model?
-///
/// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri
/// currently implements it, but it seems like this may be something to check against in the
/// validator.
@@ -1071,6 +1067,16 @@ pub enum Operand<'tcx> {
/// in [UCG#188]. You should not emit MIR that may attempt a subsequent second load of this
/// place without first re-initializing it.
///
+ /// **Needs clarification:** The operational impact of `Move` is unclear. Currently (both in
+ /// Miri and codegen) it has no effect at all unless it appears in an argument to `Call`; for
+ /// `Call` it allows the argument to be passed to the callee "in-place", i.e. the callee might
+ /// just get a reference to this place instead of a full copy. Miri implements this with a
+ /// combination of aliasing model "protectors" and putting `uninit` into the place. Ralf
+ /// proposes that we don't want these semantics for `Move` in regular assignments, because
+ /// loading a place should not have side-effects, and the aliasing model "protectors" are
+ /// inherently tied to a function call. Are these the semantics we want for MIR? Is this
+ /// something we can even decide without knowing more about Rust's memory model?
+ ///
/// [UCG#188]: https://github.com/rust-lang/unsafe-code-guidelines/issues/188
Move(Place<'tcx>),
@@ -1262,10 +1268,10 @@ pub enum AggregateKind<'tcx> {
/// active field number and is present only for union expressions
/// -- e.g., for a union expression `SomeUnion { c: .. }`, the
/// active field index would identity the field `c`
- Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
+ Adt(DefId, VariantIdx, GenericArgsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
- Closure(DefId, SubstsRef<'tcx>),
- Generator(DefId, SubstsRef<'tcx>, hir::Movability),
+ Closure(DefId, GenericArgsRef<'tcx>),
+ Generator(DefId, GenericArgsRef<'tcx>, hir::Movability),
}
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 8618a5315..f79697936 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -35,7 +35,7 @@ impl<'tcx> PlaceTy<'tcx> {
#[instrument(level = "debug", skip(tcx), ret)]
pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
match self.ty.kind() {
- ty::Adt(adt_def, substs) => {
+ ty::Adt(adt_def, args) => {
let variant_def = match self.variant_index {
None => adt_def.non_enum_variant(),
Some(variant_index) => {
@@ -44,7 +44,7 @@ impl<'tcx> PlaceTy<'tcx> {
}
};
let field_def = &variant_def.fields[f];
- field_def.ty(tcx, substs)
+ field_def.ty(tcx, args)
}
ty::Tuple(tys) => tys[f.index()],
_ => bug!("extracting field of non-tuple non-adt: {:?}", self),
@@ -198,10 +198,10 @@ impl<'tcx> Rvalue<'tcx> {
AggregateKind::Tuple => {
Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx)))
}
- AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs),
- AggregateKind::Closure(did, substs) => Ty::new_closure(tcx, did, substs),
- AggregateKind::Generator(did, substs, movability) => {
- Ty::new_generator(tcx, did, substs, movability)
+ AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args),
+ AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args),
+ AggregateKind::Generator(did, args, movability) => {
+ Ty::new_generator(tcx, did, args, movability)
}
},
Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 1b9c1438f..1f878d23b 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -10,6 +10,7 @@ use std::iter;
use std::slice;
pub use super::query::*;
+use super::*;
#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
pub struct SwitchTargets {
@@ -280,7 +281,7 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
match (successor_count, unwind) {
(0, None) => Ok(()),
- (0, Some(unwind)) => write!(fmt, " -> {}", unwind),
+ (0, Some(unwind)) => write!(fmt, " -> {unwind}"),
(1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
_ => {
write!(fmt, " -> [")?;
@@ -307,22 +308,22 @@ impl<'tcx> TerminatorKind<'tcx> {
use self::TerminatorKind::*;
match self {
Goto { .. } => write!(fmt, "goto"),
- SwitchInt { discr, .. } => write!(fmt, "switchInt({:?})", discr),
+ SwitchInt { discr, .. } => write!(fmt, "switchInt({discr:?})"),
Return => write!(fmt, "return"),
GeneratorDrop => write!(fmt, "generator_drop"),
Resume => write!(fmt, "resume"),
Terminate => write!(fmt, "abort"),
- Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value),
+ Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"),
Unreachable => write!(fmt, "unreachable"),
- Drop { place, .. } => write!(fmt, "drop({:?})", place),
+ Drop { place, .. } => write!(fmt, "drop({place:?})"),
Call { func, args, destination, .. } => {
- write!(fmt, "{:?} = ", destination)?;
- write!(fmt, "{:?}(", func)?;
+ write!(fmt, "{destination:?} = ")?;
+ write!(fmt, "{func:?}(")?;
for (index, arg) in args.iter().enumerate() {
if index > 0 {
write!(fmt, ", ")?;
}
- write!(fmt, "{:?}", arg)?;
+ write!(fmt, "{arg:?}")?;
}
write!(fmt, ")")
}
@@ -331,7 +332,7 @@ impl<'tcx> TerminatorKind<'tcx> {
if !expected {
write!(fmt, "!")?;
}
- write!(fmt, "{:?}, ", cond)?;
+ write!(fmt, "{cond:?}, ")?;
msg.fmt_assert_args(fmt)?;
write!(fmt, ")")
}
@@ -344,7 +345,7 @@ impl<'tcx> TerminatorKind<'tcx> {
let print_late = |&late| if late { "late" } else { "" };
match op {
InlineAsmOperand::In { reg, value } => {
- write!(fmt, "in({}) {:?}", reg, value)?;
+ write!(fmt, "in({reg}) {value:?}")?;
}
InlineAsmOperand::Out { reg, late, place: Some(place) } => {
write!(fmt, "{}out({}) {:?}", print_late(late), reg, place)?;
@@ -371,17 +372,17 @@ impl<'tcx> TerminatorKind<'tcx> {
write!(fmt, "in{}out({}) {:?} => _", print_late(late), reg, in_value)?;
}
InlineAsmOperand::Const { value } => {
- write!(fmt, "const {:?}", value)?;
+ write!(fmt, "const {value:?}")?;
}
InlineAsmOperand::SymFn { value } => {
- write!(fmt, "sym_fn {:?}", value)?;
+ write!(fmt, "sym_fn {value:?}")?;
}
InlineAsmOperand::SymStatic { def_id } => {
- write!(fmt, "sym_static {:?}", def_id)?;
+ write!(fmt, "sym_static {def_id:?}")?;
}
}
}
- write!(fmt, ", options({:?}))", options)
+ write!(fmt, ", options({options:?}))")
}
}
}
@@ -430,3 +431,108 @@ impl<'tcx> TerminatorKind<'tcx> {
}
}
}
+
+#[derive(Copy, Clone, Debug)]
+pub enum TerminatorEdges<'mir, 'tcx> {
+ /// For terminators that have no successor, like `return`.
+ None,
+ /// For terminators that a single successor, like `goto`, and `assert` without cleanup block.
+ Single(BasicBlock),
+ /// For terminators that two successors, `assert` with cleanup block and `falseEdge`.
+ Double(BasicBlock, BasicBlock),
+ /// Special action for `Yield`, `Call` and `InlineAsm` terminators.
+ AssignOnReturn {
+ return_: Option<BasicBlock>,
+ unwind: UnwindAction,
+ place: CallReturnPlaces<'mir, 'tcx>,
+ },
+ /// Special edge for `SwitchInt`.
+ SwitchInt { targets: &'mir SwitchTargets, discr: &'mir Operand<'tcx> },
+}
+
+/// List of places that are written to after a successful (non-unwind) return
+/// from a `Call`, `Yield` or `InlineAsm`.
+#[derive(Copy, Clone, Debug)]
+pub enum CallReturnPlaces<'a, 'tcx> {
+ Call(Place<'tcx>),
+ Yield(Place<'tcx>),
+ InlineAsm(&'a [InlineAsmOperand<'tcx>]),
+}
+
+impl<'tcx> CallReturnPlaces<'_, 'tcx> {
+ pub fn for_each(&self, mut f: impl FnMut(Place<'tcx>)) {
+ match *self {
+ Self::Call(place) | Self::Yield(place) => f(place),
+ Self::InlineAsm(operands) => {
+ for op in operands {
+ match *op {
+ InlineAsmOperand::Out { place: Some(place), .. }
+ | InlineAsmOperand::InOut { out_place: Some(place), .. } => f(place),
+ _ => {}
+ }
+ }
+ }
+ }
+ }
+}
+
+impl<'tcx> Terminator<'tcx> {
+ pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
+ self.kind.edges()
+ }
+}
+
+impl<'tcx> TerminatorKind<'tcx> {
+ pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
+ use TerminatorKind::*;
+ match *self {
+ Return | Resume | Terminate | GeneratorDrop | Unreachable => TerminatorEdges::None,
+
+ Goto { target } => TerminatorEdges::Single(target),
+
+ Assert { target, unwind, expected: _, msg: _, cond: _ }
+ | Drop { target, unwind, place: _, replace: _ }
+ | FalseUnwind { real_target: target, unwind } => match unwind {
+ UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind),
+ UnwindAction::Continue | UnwindAction::Terminate | UnwindAction::Unreachable => {
+ TerminatorEdges::Single(target)
+ }
+ },
+
+ FalseEdge { real_target, imaginary_target } => {
+ TerminatorEdges::Double(real_target, imaginary_target)
+ }
+
+ Yield { resume: target, drop, resume_arg, value: _ } => {
+ TerminatorEdges::AssignOnReturn {
+ return_: Some(target),
+ unwind: drop.map_or(UnwindAction::Terminate, UnwindAction::Cleanup),
+ place: CallReturnPlaces::Yield(resume_arg),
+ }
+ }
+
+ Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => {
+ TerminatorEdges::AssignOnReturn {
+ return_: target,
+ unwind,
+ place: CallReturnPlaces::Call(destination),
+ }
+ }
+
+ InlineAsm {
+ template: _,
+ ref operands,
+ options: _,
+ line_spans: _,
+ destination,
+ unwind,
+ } => TerminatorEdges::AssignOnReturn {
+ return_: destination,
+ unwind,
+ place: CallReturnPlaces::InlineAsm(operands),
+ },
+
+ SwitchInt { ref targets, ref discr } => TerminatorEdges::SwitchInt { targets, discr },
+ }
+ }
+}
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 205dc9ec7..069b38591 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -63,7 +63,7 @@
//! `is_cleanup` above.
use crate::mir::*;
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
use crate::ty::{self, CanonicalUserTypeAnnotation, Ty};
use rustc_span::Span;
@@ -245,12 +245,12 @@ macro_rules! make_mir_visitor {
self.super_region(region);
}
- fn visit_substs(
+ fn visit_args(
&mut self,
- substs: & $($mutability)? SubstsRef<'tcx>,
+ args: & $($mutability)? GenericArgsRef<'tcx>,
_: Location,
) {
- self.super_substs(substs);
+ self.super_args(args);
}
fn visit_local_decl(
@@ -335,7 +335,7 @@ macro_rules! make_mir_visitor {
self.visit_span($(& $mutability)? *callsite_span);
- let ty::Instance { def: callee_def, substs: callee_substs } = callee;
+ let ty::Instance { def: callee_def, args: callee_args } = callee;
match callee_def {
ty::InstanceDef::Item(_def_id) => {}
@@ -355,7 +355,7 @@ macro_rules! make_mir_visitor {
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
}
- self.visit_substs(callee_substs, location);
+ self.visit_args(callee_args, location);
}
if let Some(inlined_parent_scope) = inlined_parent_scope {
self.visit_source_scope($(& $mutability)? *inlined_parent_scope);
@@ -721,24 +721,24 @@ macro_rules! make_mir_visitor {
AggregateKind::Adt(
_adt_def,
_variant_index,
- substs,
- _user_substs,
+ args,
+ _user_args,
_active_field_index
) => {
- self.visit_substs(substs, location);
+ self.visit_args(args, location);
}
AggregateKind::Closure(
_,
- closure_substs
+ closure_args
) => {
- self.visit_substs(closure_substs, location);
+ self.visit_args(closure_args, location);
}
AggregateKind::Generator(
_,
- generator_substs,
+ generator_args,
_movability,
) => {
- self.visit_substs(generator_substs, location);
+ self.visit_args(generator_args, location);
}
}
@@ -840,7 +840,6 @@ macro_rules! make_mir_visitor {
source_info,
value,
argument_index: _,
- references: _,
} = var_debug_info;
self.visit_source_info(source_info);
@@ -933,7 +932,7 @@ macro_rules! make_mir_visitor {
fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {
}
- fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
+ fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {
}
// Convenience methods