summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_transform
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:13:23 +0000
commit20431706a863f92cb37dc512fef6e48d192aaf2c (patch)
tree2867f13f5fd5437ba628c67d7f87309ccadcd286 /compiler/rustc_mir_transform
parentReleasing progress-linux version 1.65.0+dfsg1-2~progress7.99u1. (diff)
downloadrustc-20431706a863f92cb37dc512fef6e48d192aaf2c.tar.xz
rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.zip
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_mir_transform')
-rw-r--r--compiler/rustc_mir_transform/Cargo.toml1
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs18
-rw-r--r--compiler/rustc_mir_transform/src/check_packed_ref.rs40
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs24
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs6
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs47
-rw-r--r--compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml1
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs248
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs1
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs14
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs22
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs3
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs47
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs24
-rw-r--r--compiler/rustc_mir_transform/src/marker.rs20
-rw-r--r--compiler/rustc_mir_transform/src/pass_manager.rs89
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs8
17 files changed, 414 insertions, 199 deletions
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index 85b7a4af5..53545cff0 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
itertools = "0.10.1"
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index 8838b14c5..fa5f392fa 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{DiagnosticBuilder, LintDiagnosticBuilder};
+use rustc_errors::{DiagnosticBuilder, DiagnosticMessage};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
@@ -63,7 +63,10 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
place: &Place<'tcx>,
const_item: DefId,
location: Location,
- decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) -> DiagnosticBuilder<'b, ()>,
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'a mut DiagnosticBuilder<'b, ()>,
+ ) -> &'a mut DiagnosticBuilder<'b, ()>,
) {
// Don't lint on borrowing/assigning when a dereference is involved.
// If we 'leave' the temporary via a dereference, we must
@@ -84,10 +87,10 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
CONST_ITEM_MUTATION,
lint_root,
source_info.span,
+ msg,
|lint| {
decorate(lint)
.span_note(self.tcx.def_span(const_item), "`const` item defined here")
- .emit();
},
);
}
@@ -102,10 +105,8 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
// so emitting a lint would be redundant.
if !lhs.projection.is_empty() {
if let Some(def_id) = self.is_const_item_without_destructor(lhs.local) {
- self.lint_const_item_usage(&lhs, def_id, loc, |lint| {
- let mut lint = lint.build("attempting to modify a `const` item");
- lint.note("each usage of a `const` item creates a new temporary; the original `const` item will not be modified");
- lint
+ self.lint_const_item_usage(&lhs, def_id, loc, "attempting to modify a `const` item",|lint| {
+ lint.note("each usage of a `const` item creates a new temporary; the original `const` item will not be modified")
})
}
}
@@ -137,8 +138,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
});
let lint_loc =
if method_did.is_some() { self.body.terminator_loc(loc.block) } else { loc };
- self.lint_const_item_usage(place, def_id, lint_loc, |lint| {
- let mut lint = lint.build("taking a mutable reference to a `const` item");
+ self.lint_const_item_usage(place, def_id, lint_loc, "taking a mutable reference to a `const` item", |lint| {
lint
.note("each usage of a `const` item creates a new temporary")
.note("the mutable reference will refer to this temporary, not the original `const` item");
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 3b7ba3f9a..51abcf511 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -33,21 +33,27 @@ struct PackedRefChecker<'a, 'tcx> {
fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- tcx.struct_span_lint_hir(UNALIGNED_REFERENCES, lint_hir_id, tcx.def_span(def_id), |lint| {
- // FIXME: when we make this a hard error, this should have its
- // own error code.
- let extra = if tcx.generics_of(def_id).own_requires_monomorphization() {
- "with type or const parameters"
- } else {
- "that does not derive `Copy`"
- };
- let message = format!(
- "`{}` can't be derived on this `#[repr(packed)]` struct {}",
- tcx.item_name(tcx.trait_id_of_impl(def_id.to_def_id()).expect("derived trait name")),
- extra
- );
- lint.build(message).emit();
- });
+ // FIXME: when we make this a hard error, this should have its
+ // own error code.
+
+ let extra = if tcx.generics_of(def_id).own_requires_monomorphization() {
+ "with type or const parameters"
+ } else {
+ "that does not derive `Copy`"
+ };
+ let message = format!(
+ "`{}` can't be derived on this `#[repr(packed)]` struct {}",
+ tcx.item_name(tcx.trait_id_of_impl(def_id.to_def_id()).expect("derived trait name")),
+ extra
+ );
+
+ tcx.struct_span_lint_hir(
+ UNALIGNED_REFERENCES,
+ lint_hir_id,
+ tcx.def_span(def_id),
+ message,
+ |lint| lint,
+ );
}
impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
@@ -86,8 +92,9 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
UNALIGNED_REFERENCES,
lint_root,
source_info.span,
+ "reference to packed field is unaligned",
|lint| {
- lint.build("reference to packed field is unaligned")
+ lint
.note(
"fields of packed structs are not properly aligned, and creating \
a misaligned reference is undefined behavior (even if that \
@@ -98,7 +105,6 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
(loads and stores via `*p` must be properly aligned even when using raw pointers)"
)
- .emit();
},
);
}
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index beff19a3a..f8f04214a 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -312,7 +312,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
} else if !place
.ty(self.body, self.tcx)
.ty
- .is_freeze(self.tcx.at(self.source_info.span), self.param_env)
+ .is_freeze(self.tcx, self.param_env)
{
UnsafetyViolationDetails::BorrowOfLayoutConstrainedField
} else {
@@ -489,21 +489,20 @@ fn unsafety_check_result<'tcx>(
fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id));
- tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| {
- let msg = "unnecessary `unsafe` block";
- let mut db = lint.build(msg);
- db.span_label(span, msg);
+ let msg = "unnecessary `unsafe` block";
+ tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, msg, |lint| {
+ lint.span_label(span, msg);
match kind {
UnusedUnsafe::Unused => {}
UnusedUnsafe::InUnsafeBlock(id) => {
- db.span_label(
+ lint.span_label(
tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
"because it's nested under this `unsafe` block",
);
}
}
- db.emit();
+ lint
});
}
@@ -543,15 +542,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
UNSAFE_OP_IN_UNSAFE_FN,
lint_root,
source_info.span,
- |lint| {
- lint.build(&format!(
- "{} is unsafe and requires unsafe block (error E0133)",
- description,
- ))
- .span_label(source_info.span, description)
- .note(note)
- .emit();
- },
+ format!("{} is unsafe and requires unsafe block (error E0133)", description,),
+ |lint| lint.span_label(source_info.span, description).note(note),
),
}
}
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 7a2a15a84..4e4515888 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -17,7 +17,7 @@ use rustc_middle::mir::{
RETURN_PLACE,
};
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
use rustc_span::{def_id::DefId, Span};
use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
@@ -471,7 +471,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
return None;
}
- self.ecx.mir_const_to_op(&c.literal, None).ok()
+ self.ecx.const_to_op(&c.literal, None).ok()
}
/// Returns the value, if any, of evaluating `place`.
@@ -633,7 +633,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
if !rvalue
.ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx)
- .is_sized(self.ecx.tcx, self.param_env)
+ .is_sized(*self.ecx.tcx, self.param_env)
{
// the interpreter doesn't support unsized locals (only unsized arguments),
// but rustc does (in a kinda broken way), so we have to skip them here
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 37e78f4ac..479c4e577 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -16,12 +16,12 @@ use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{
- AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand, Place,
- Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator,
- TerminatorKind, UnOp, RETURN_PLACE,
+ AssertKind, BinOp, Body, Constant, Local, LocalDecl, Location, Operand, Place, Rvalue,
+ SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind,
+ UnOp, RETURN_PLACE,
};
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, ConstInt, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable};
use rustc_session::lint;
use rustc_span::Span;
@@ -286,39 +286,22 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
/// Returns the value, if any, of evaluating `c`.
- fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
+ fn eval_constant(
+ &mut self,
+ c: &Constant<'tcx>,
+ _source_info: SourceInfo,
+ ) -> Option<OpTy<'tcx>> {
// FIXME we need to revisit this for #67176
if c.needs_subst() {
return None;
}
- match self.ecx.mir_const_to_op(&c.literal, None) {
+ match self.ecx.const_to_op(&c.literal, None) {
Ok(op) => Some(op),
Err(error) => {
let tcx = self.ecx.tcx.at(c.span);
let err = ConstEvalErr::new(&self.ecx, error, Some(c.span));
- if let Some(lint_root) = self.lint_root(source_info) {
- let lint_only = match c.literal {
- ConstantKind::Ty(ct) => ct.needs_subst(),
- ConstantKind::Unevaluated(
- ty::Unevaluated { def: _, substs: _, promoted: Some(_) },
- _,
- ) => {
- // Promoteds must lint and not error as the user didn't ask for them
- true
- }
- ConstantKind::Unevaluated(..) | ConstantKind::Val(..) => c.needs_subst(),
- };
- if lint_only {
- // Out of backwards compatibility we cannot report hard errors in unused
- // generic functions using associated constants of the generic parameters.
- err.report_as_lint(tcx, "erroneous constant used", lint_root, Some(c.span));
- } else {
- err.report_as_error(tcx, "erroneous constant used");
- }
- } else {
- err.report_as_error(tcx, "erroneous constant used");
- }
+ err.report_as_error(tcx, "erroneous constant used");
None
}
}
@@ -347,10 +330,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
panic: AssertKind<impl std::fmt::Debug>,
) {
if let Some(lint_root) = self.lint_root(source_info) {
- self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
- let mut err = lint.build(message);
- err.span_label(source_info.span, format!("{:?}", panic));
- err.emit();
+ self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, message, |lint| {
+ lint.span_label(source_info.span, format!("{:?}", panic))
});
}
}
@@ -519,7 +500,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
if !rvalue
.ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx)
- .is_sized(self.ecx.tcx, self.param_env)
+ .is_sized(*self.ecx.tcx, self.param_env)
{
// the interpreter doesn't support unsized locals (only unsized arguments),
// but rustc does (in a kinda broken way), so we have to skip them here
diff --git a/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml
index f5e8b6565..f753caa91 100644
--- a/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml
+++ b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml
@@ -5,4 +5,3 @@ edition = "2021"
[lib]
proc-macro = true
-doctest = false
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
new file mode 100644
index 000000000..28b1c5a48
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -0,0 +1,248 @@
+//! Deduces supplementary parameter attributes from MIR.
+//!
+//! Deduced parameter attributes are those that can only be soundly determined by examining the
+//! body of the function instead of just the signature. These can be useful for optimization
+//! purposes on a best-effort basis. We compute them here and store them into the crate metadata so
+//! dependent crates can use them.
+
+use rustc_hir::def_id::DefId;
+use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
+use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt};
+use rustc_session::config::OptLevel;
+
+/// A visitor that determines which arguments have been mutated. We can't use the mutability field
+/// on LocalDecl for this because it has no meaning post-optimization.
+struct DeduceReadOnly {
+ /// Each bit is indexed by argument number, starting at zero (so 0 corresponds to local decl
+ /// 1). The bit is true if the argument may have been mutated or false if we know it hasn't
+ /// been up to the point we're at.
+ mutable_args: BitSet<usize>,
+}
+
+impl DeduceReadOnly {
+ /// Returns a new DeduceReadOnly instance.
+ fn new(arg_count: usize) -> Self {
+ Self { mutable_args: BitSet::new_empty(arg_count) }
+ }
+}
+
+impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
+ fn visit_local(&mut self, local: Local, mut context: PlaceContext, _: Location) {
+ // We're only interested in arguments.
+ if local == RETURN_PLACE || local.index() > self.mutable_args.domain_size() {
+ return;
+ }
+
+ // Replace place contexts that are moves with copies. This is safe in all cases except
+ // function argument position, which we already handled in `visit_terminator()` by using the
+ // ArgumentChecker. See the comment in that method for more details.
+ //
+ // In the future, we might want to move this out into a separate pass, but for now let's
+ // just do it on the fly because that's faster.
+ if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)) {
+ context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
+ }
+
+ match context {
+ PlaceContext::MutatingUse(..)
+ | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => {
+ // This is a mutation, so mark it as such.
+ self.mutable_args.insert(local.index() - 1);
+ }
+ PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => {
+ // Not mutating, so it's fine.
+ }
+ }
+ }
+
+ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
+ // OK, this is subtle. Suppose that we're trying to deduce whether `x` in `f` is read-only
+ // and we have the following:
+ //
+ // fn f(x: BigStruct) { g(x) }
+ // fn g(mut y: BigStruct) { y.foo = 1 }
+ //
+ // If, at the generated MIR level, `f` turned into something like:
+ //
+ // fn f(_1: BigStruct) -> () {
+ // let mut _0: ();
+ // bb0: {
+ // _0 = g(move _1) -> bb1;
+ // }
+ // ...
+ // }
+ //
+ // then it would be incorrect to mark `x` (i.e. `_1`) as `readonly`, because `g`'s write to
+ // its copy of the indirect parameter would actually be a write directly to the pointer that
+ // `f` passes. Note that function arguments are the only situation in which this problem can
+ // arise: every other use of `move` in MIR doesn't actually write to the value it moves
+ // from.
+ //
+ // Anyway, right now this situation doesn't actually arise in practice. Instead, the MIR for
+ // that function looks like this:
+ //
+ // fn f(_1: BigStruct) -> () {
+ // let mut _0: ();
+ // let mut _2: BigStruct;
+ // bb0: {
+ // _2 = move _1;
+ // _0 = g(move _2) -> bb1;
+ // }
+ // ...
+ // }
+ //
+ // Because of that extra move that MIR construction inserts, `x` (i.e. `_1`) can *in
+ // practice* safely be marked `readonly`.
+ //
+ // To handle the possibility that other optimizations (for example, destination propagation)
+ // might someday generate MIR like the first example above, we panic upon seeing an argument
+ // to *our* function that is directly moved into *another* function as an argument. Having
+ // eliminated that problematic case, we can safely treat moves as copies in this analysis.
+ //
+ // In the future, if MIR optimizations cause arguments of a caller to be directly moved into
+ // the argument of a callee, we can just add that argument to `mutated_args` instead of
+ // panicking.
+ //
+ // Note that, because the problematic MIR is never actually generated, we can't add a test
+ // case for this.
+
+ if let TerminatorKind::Call { ref args, .. } = terminator.kind {
+ for arg in args {
+ if let Operand::Move(_) = *arg {
+ // ArgumentChecker panics if a direct move of an argument from a caller to a
+ // callee was detected.
+ //
+ // If, in the future, MIR optimizations cause arguments to be moved directly
+ // from callers to callees, change the panic to instead add the argument in
+ // question to `mutating_uses`.
+ ArgumentChecker::new(self.mutable_args.domain_size())
+ .visit_operand(arg, location)
+ }
+ }
+ };
+
+ self.super_terminator(terminator, location);
+ }
+}
+
+/// A visitor that simply panics if a direct move of an argument from a caller to a callee was
+/// detected.
+struct ArgumentChecker {
+ /// The number of arguments to the calling function.
+ arg_count: usize,
+}
+
+impl ArgumentChecker {
+ /// Creates a new ArgumentChecker.
+ fn new(arg_count: usize) -> Self {
+ Self { arg_count }
+ }
+}
+
+impl<'tcx> Visitor<'tcx> for ArgumentChecker {
+ fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
+ // Check to make sure that, if this local is an argument, we didn't move directly from it.
+ if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move))
+ && local != RETURN_PLACE
+ && local.index() <= self.arg_count
+ {
+ // If, in the future, MIR optimizations cause arguments to be moved directly from
+ // callers to callees, change this panic to instead add the argument in question to
+ // `mutating_uses`.
+ panic!("Detected a direct move from a caller's argument to a callee's argument!")
+ }
+ }
+}
+
+/// Returns true if values of a given type will never be passed indirectly, regardless of ABI.
+fn type_will_always_be_passed_directly<'tcx>(ty: Ty<'tcx>) -> bool {
+ matches!(
+ ty.kind(),
+ ty::Bool
+ | ty::Char
+ | ty::Float(..)
+ | ty::Int(..)
+ | ty::RawPtr(..)
+ | ty::Ref(..)
+ | ty::Slice(..)
+ | ty::Uint(..)
+ )
+}
+
+/// Returns the deduced parameter attributes for a function.
+///
+/// Deduced parameter attributes are those that can only be soundly determined by examining the
+/// body of the function instead of just the signature. These can be useful for optimization
+/// purposes on a best-effort basis. We compute them here and store them into the crate metadata so
+/// dependent crates can use them.
+pub fn deduced_param_attrs<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [DeducedParamAttrs] {
+ // This computation is unfortunately rather expensive, so don't do it unless we're optimizing.
+ // Also skip it in incremental mode.
+ if tcx.sess.opts.optimize == OptLevel::No || tcx.sess.opts.incremental.is_some() {
+ return &[];
+ }
+
+ // If the Freeze language item isn't present, then don't bother.
+ if tcx.lang_items().freeze_trait().is_none() {
+ return &[];
+ }
+
+ // Codegen won't use this information for anything if all the function parameters are passed
+ // directly. Detect that and bail, for compilation speed.
+ let fn_ty = tcx.type_of(def_id);
+ if matches!(fn_ty.kind(), ty::FnDef(..)) {
+ if fn_ty
+ .fn_sig(tcx)
+ .inputs()
+ .skip_binder()
+ .iter()
+ .cloned()
+ .all(type_will_always_be_passed_directly)
+ {
+ return &[];
+ }
+ }
+
+ // Don't deduce any attributes for functions that have no MIR.
+ if !tcx.is_mir_available(def_id) {
+ return &[];
+ }
+
+ // Deduced attributes for other crates should be read from the metadata instead of via this
+ // function.
+ debug_assert!(def_id.is_local());
+
+ // Grab the optimized MIR. Analyze it to determine which arguments have been mutated.
+ let body: &Body<'tcx> = tcx.optimized_mir(def_id);
+ let mut deduce_read_only = DeduceReadOnly::new(body.arg_count);
+ deduce_read_only.visit_body(body);
+
+ // Set the `readonly` attribute for every argument that we concluded is immutable and that
+ // contains no UnsafeCells.
+ //
+ // FIXME: This is overly conservative around generic parameters: `is_freeze()` will always
+ // return false for them. For a description of alternatives that could do a better job here,
+ // see [1].
+ //
+ // [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
+ let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
+ body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
+ |(arg_index, local_decl)| DeducedParamAttrs {
+ read_only: !deduce_read_only.mutable_args.contains(arg_index)
+ && local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()),
+ },
+ ),
+ );
+
+ // Trailing parameters past the size of the `deduced_param_attrs` array are assumed to have the
+ // default set of attributes, so we don't have to store them explicitly. Pop them off to save a
+ // few bytes in metadata.
+ while deduced_param_attrs.last() == Some(&DeducedParamAttrs::default()) {
+ let last_index = deduced_param_attrs.len() - 1;
+ deduced_param_attrs = &mut deduced_param_attrs[0..last_index];
+ }
+
+ deduced_param_attrs
+}
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 294af2455..ef8d6bb65 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -8,7 +8,6 @@ use rustc_index::vec::Idx;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{Ty, TyCtxt};
/// Constructs the types used when accessing a Box's pointer
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 7522a50a8..1244c1802 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -106,14 +106,12 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
.lint_root;
let span = terminator.source_info.span;
- tcx.struct_span_lint_hir(FFI_UNWIND_CALLS, lint_root, span, |lint| {
- let msg = match fn_def_id {
- Some(_) => "call to foreign function with FFI-unwind ABI",
- None => "call to function pointer with FFI-unwind ABI",
- };
- let mut db = lint.build(msg);
- db.span_label(span, msg);
- db.emit();
+ let msg = match fn_def_id {
+ Some(_) => "call to foreign function with FFI-unwind ABI",
+ None => "call to function pointer with FFI-unwind ABI",
+ };
+ tcx.struct_span_lint_hir(FFI_UNWIND_CALLS, lint_root, span, msg, |lint| {
+ lint.span_label(span, msg)
});
tainted = true;
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 2e4fe1e3e..469566694 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -3,11 +3,7 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
-use rustc_middle::ty::{
- self,
- subst::{GenericArgKind, Subst, SubstsRef},
- EarlyBinder, PredicateKind, Ty, TyCtxt,
-};
+use rustc_middle::ty::{self, EarlyBinder, GenericArgKind, PredicateKind, SubstsRef, Ty, TyCtxt};
use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
use rustc_span::{symbol::sym, Span};
use rustc_target::spec::abi::Abi;
@@ -183,11 +179,15 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
let num_args = fn_sig.inputs().map_bound(|inputs| inputs.len()).skip_binder();
let variadic = if fn_sig.c_variadic() { ", ..." } else { "" };
let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" };
- self.tcx.struct_span_lint_hir(FUNCTION_ITEM_REFERENCES, lint_root, span, |lint| {
- lint.build("taking a reference to a function item does not give a function pointer")
- .span_suggestion(
+ self.tcx.struct_span_lint_hir(
+ FUNCTION_ITEM_REFERENCES,
+ lint_root,
+ span,
+ "taking a reference to a function item does not give a function pointer",
+ |lint| {
+ lint.span_suggestion(
span,
- &format!("cast `{}` to obtain a function pointer", ident),
+ format!("cast `{}` to obtain a function pointer", ident),
format!(
"{} as {}{}fn({}{}){}",
if params.is_empty() { ident } else { format!("{}::<{}>", ident, params) },
@@ -199,7 +199,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
),
Applicability::Unspecified,
)
- .emit();
- });
+ },
+ );
}
}
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 705cf776f..c833de3a8 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -61,9 +61,8 @@ use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::dump_mir;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
-use rustc_middle::ty::GeneratorSubsts;
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+use rustc_middle::ty::{GeneratorSubsts, SubstsRef};
use rustc_mir_dataflow::impls::{
MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
};
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index d00a384cb..780b91d92 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -7,7 +7,6 @@ use rustc_index::vec::Idx;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_session::config::OptLevel;
use rustc_span::def_id::DefId;
@@ -606,7 +605,7 @@ impl<'tcx> Inliner<'tcx> {
caller_body.required_consts.extend(
callee_body.required_consts.iter().copied().filter(|&ct| match ct.literal {
ConstantKind::Ty(_) => {
- bug!("should never encounter ty::Unevaluated in `required_consts`")
+ bug!("should never encounter ty::UnevaluatedConst in `required_consts`")
}
ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => true,
}),
@@ -978,6 +977,21 @@ impl Integrator<'_, '_> {
trace!("mapping block `{:?}` to `{:?}`", block, new);
new
}
+
+ fn map_unwind(&self, unwind: Option<BasicBlock>) -> Option<BasicBlock> {
+ if self.in_cleanup_block {
+ if unwind.is_some() {
+ bug!("cleanup on cleanup block");
+ }
+ return unwind;
+ }
+
+ match unwind {
+ Some(target) => Some(self.map_block(target)),
+ // Add an unwind edge to the original call's cleanup block
+ None => self.cleanup_block,
+ }
+ }
}
impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
@@ -1086,35 +1100,17 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
TerminatorKind::Drop { ref mut target, ref mut unwind, .. }
| TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => {
*target = self.map_block(*target);
- if let Some(tgt) = *unwind {
- *unwind = Some(self.map_block(tgt));
- } else if !self.in_cleanup_block {
- // Unless this drop is in a cleanup block, add an unwind edge to
- // the original call's cleanup block
- *unwind = self.cleanup_block;
- }
+ *unwind = self.map_unwind(*unwind);
}
TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
if let Some(ref mut tgt) = *target {
*tgt = self.map_block(*tgt);
}
- if let Some(tgt) = *cleanup {
- *cleanup = Some(self.map_block(tgt));
- } else if !self.in_cleanup_block {
- // Unless this call is in a cleanup block, add an unwind edge to
- // the original call's cleanup block
- *cleanup = self.cleanup_block;
- }
+ *cleanup = self.map_unwind(*cleanup);
}
TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
*target = self.map_block(*target);
- if let Some(tgt) = *cleanup {
- *cleanup = Some(self.map_block(tgt));
- } else if !self.in_cleanup_block {
- // Unless this assert is in a cleanup block, add an unwind edge to
- // the original call's cleanup block
- *cleanup = self.cleanup_block;
- }
+ *cleanup = self.map_unwind(*cleanup);
}
TerminatorKind::Return => {
terminator.kind = if let Some(tgt) = self.callsite.target {
@@ -1142,11 +1138,8 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => {
if let Some(ref mut tgt) = *destination {
*tgt = self.map_block(*tgt);
- } else if !self.in_cleanup_block {
- // Unless this inline asm is in a cleanup block, add an unwind edge to
- // the original call's cleanup block
- *cleanup = self.cleanup_block;
}
+ *cleanup = self.map_unwind(*cleanup);
}
}
}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index e6fc85595..5be223254 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -1,7 +1,6 @@
#![allow(rustc::potential_query_instability)]
#![feature(box_patterns)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(never_type)]
@@ -57,6 +56,7 @@ mod const_prop_lint;
mod coverage;
mod dead_store_elimination;
mod deaggregator;
+mod deduce_param_attrs;
mod deduplicate_blocks;
mod deref_separator;
mod dest_prop;
@@ -71,7 +71,6 @@ mod inline;
mod instcombine;
mod lower_intrinsics;
mod lower_slice_len;
-mod marker;
mod match_branches;
mod multiple_return_terminators;
mod normalize_array_len;
@@ -140,6 +139,7 @@ pub fn provide(providers: &mut Providers) {
promoted_mir_of_const_arg: |tcx, (did, param_did)| {
promoted_mir(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
},
+ deduced_param_attrs: deduce_param_attrs::deduced_param_attrs,
..*providers
};
}
@@ -302,6 +302,7 @@ fn mir_const<'tcx>(
&simplify::SimplifyCfg::new("initial"),
&rustc_peek::SanityCheck, // Just a lint
],
+ None,
);
tcx.alloc_steal_mir(body)
}
@@ -341,6 +342,7 @@ fn mir_promoted<'tcx>(
&simplify::SimplifyCfg::new("promote-consts"),
&coverage::InstrumentCoverage,
],
+ Some(MirPhase::Analysis(AnalysisPhase::Initial)),
);
let promoted = promote_pass.promoted_fragments.into_inner();
@@ -408,10 +410,8 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
pm::run_passes(
tcx,
&mut body,
- &[
- &const_prop::ConstProp,
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)),
- ],
+ &[&const_prop::ConstProp],
+ Some(MirPhase::Runtime(RuntimePhase::Optimized)),
);
}
}
@@ -473,6 +473,7 @@ fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>
&remove_uninit_drops::RemoveUninitDrops,
&simplify::SimplifyCfg::new("remove-false-edges"),
],
+ None,
);
check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint
}
@@ -497,10 +498,9 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&cleanup_post_borrowck::CleanupNonCodegenStatements,
&simplify::SimplifyCfg::new("early-opt"),
&deref_separator::Derefer,
- &marker::PhaseChange(MirPhase::Analysis(AnalysisPhase::PostCleanup)),
];
- pm::run_passes(tcx, body, passes);
+ pm::run_passes(tcx, body, passes, Some(MirPhase::Analysis(AnalysisPhase::PostCleanup)));
}
/// Returns the sequence of passes that lowers analysis to runtime MIR.
@@ -525,9 +525,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// CTFE support for aggregates.
&deaggregator::Deaggregator,
&Lint(const_prop_lint::ConstProp),
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Initial)),
];
- pm::run_passes_no_validate(tcx, body, passes);
+ pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial)));
}
/// Returns the sequence of passes that do the initial cleanup of runtime MIR.
@@ -536,10 +535,9 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&elaborate_box_derefs::ElaborateBoxDerefs,
&lower_intrinsics::LowerIntrinsics,
&simplify::SimplifyCfg::new("elaborate-drops"),
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::PostCleanup)),
];
- pm::run_passes(tcx, body, passes);
+ pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup)));
}
fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -590,10 +588,10 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&deduplicate_blocks::DeduplicateBlocks,
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
&add_call_guards::CriticalCallEdges,
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)),
// Dump the end result for testing and debugging purposes.
&dump_mir::Marker("PreCodegen"),
],
+ Some(MirPhase::Runtime(RuntimePhase::Optimized)),
);
}
diff --git a/compiler/rustc_mir_transform/src/marker.rs b/compiler/rustc_mir_transform/src/marker.rs
deleted file mode 100644
index 06819fc1d..000000000
--- a/compiler/rustc_mir_transform/src/marker.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use std::borrow::Cow;
-
-use crate::MirPass;
-use rustc_middle::mir::{Body, MirPhase};
-use rustc_middle::ty::TyCtxt;
-
-/// Changes the MIR phase without changing the MIR itself.
-pub struct PhaseChange(pub MirPhase);
-
-impl<'tcx> MirPass<'tcx> for PhaseChange {
- fn phase_change(&self) -> Option<MirPhase> {
- Some(self.0)
- }
-
- fn name(&self) -> Cow<'_, str> {
- Cow::from(format!("PhaseChange-{:?}", self.0))
- }
-
- fn run_pass(&self, _: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {}
-}
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 67dae7146..230c6a7cb 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -66,10 +66,6 @@ where
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
self.1.run_pass(tcx, body)
}
-
- fn phase_change(&self) -> Option<MirPhase> {
- self.1.phase_change()
- }
}
/// Run the sequence of passes without validating the MIR after each pass. The MIR is still
@@ -78,23 +74,28 @@ pub fn run_passes_no_validate<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
passes: &[&dyn MirPass<'tcx>],
+ phase_change: Option<MirPhase>,
) {
- run_passes_inner(tcx, body, passes, false);
+ run_passes_inner(tcx, body, passes, phase_change, false);
}
-pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) {
- run_passes_inner(tcx, body, passes, true);
+/// The optional `phase_change` is applied after executing all the passes, if present
+pub fn run_passes<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ body: &mut Body<'tcx>,
+ passes: &[&dyn MirPass<'tcx>],
+ phase_change: Option<MirPhase>,
+) {
+ run_passes_inner(tcx, body, passes, phase_change, true);
}
fn run_passes_inner<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
passes: &[&dyn MirPass<'tcx>],
+ phase_change: Option<MirPhase>,
validate_each: bool,
) {
- let start_phase = body.phase;
- let mut cnt = 0;
-
let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir;
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
trace!(?overridden_passes);
@@ -102,7 +103,6 @@ fn run_passes_inner<'tcx>(
for pass in passes {
let name = pass.name();
- // Gather information about what we should be doing for this pass
let overridden =
overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| {
trace!(
@@ -112,32 +112,44 @@ fn run_passes_inner<'tcx>(
);
*polarity
});
- let is_enabled = overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess));
- let new_phase = pass.phase_change();
- let dump_enabled = (is_enabled && pass.is_mir_dump_enabled()) || new_phase.is_some();
- let validate = (validate && is_enabled)
- || new_phase == Some(MirPhase::Runtime(RuntimePhase::Optimized));
+ if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) {
+ continue;
+ }
+
+ let dump_enabled = pass.is_mir_dump_enabled();
if dump_enabled {
- dump_mir(tcx, body, start_phase, &name, cnt, false);
- }
- if is_enabled {
- pass.run_pass(tcx, body);
+ dump_mir_for_pass(tcx, body, &name, false);
}
- if dump_enabled {
- dump_mir(tcx, body, start_phase, &name, cnt, true);
- cnt += 1;
+ if validate {
+ validate_body(tcx, body, format!("before pass {}", name));
}
- if let Some(new_phase) = pass.phase_change() {
- if body.phase >= new_phase {
- panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase);
- }
- body.phase = new_phase;
+ pass.run_pass(tcx, body);
+
+ if dump_enabled {
+ dump_mir_for_pass(tcx, body, &name, true);
}
if validate {
validate_body(tcx, body, format!("after pass {}", name));
}
+
+ body.pass_count += 1;
+ }
+
+ if let Some(new_phase) = phase_change {
+ if body.phase >= new_phase {
+ panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase);
+ }
+
+ body.phase = new_phase;
+
+ dump_mir_for_phase_change(tcx, body);
+ if validate || new_phase == MirPhase::Runtime(RuntimePhase::Optimized) {
+ validate_body(tcx, body, format!("after phase change to {}", new_phase));
+ }
+
+ body.pass_count = 1;
}
}
@@ -145,22 +157,33 @@ pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: Strin
validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body);
}
-pub fn dump_mir<'tcx>(
+pub fn dump_mir_for_pass<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
- phase: MirPhase,
pass_name: &str,
- cnt: usize,
is_after: bool,
) {
- let phase_index = phase.phase_index();
+ let phase_index = body.phase.phase_index();
mir::dump_mir(
tcx,
- Some(&format_args!("{:03}-{:03}", phase_index, cnt)),
+ Some(&format_args!("{:03}-{:03}", phase_index, body.pass_count)),
pass_name,
if is_after { &"after" } else { &"before" },
body,
|_, _| Ok(()),
);
}
+
+pub fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
+ let phase_index = body.phase.phase_index();
+
+ mir::dump_mir(
+ tcx,
+ Some(&format_args!("{:03}-000", phase_index)),
+ &format!("{}", body.phase),
+ &"after",
+ body,
+ |_, _| Ok(()),
+ )
+}
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 882136200..4e8798b7a 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::*;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, EarlyBinder, GeneratorSubsts, Ty, TyCtxt};
use rustc_target::abi::VariantIdx;
@@ -17,7 +17,7 @@ use std::iter;
use crate::util::expand_aggregate;
use crate::{
- abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, marker,
+ abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator,
pass_manager as pm, remove_noop_landing_pads, simplify,
};
use rustc_middle::mir::patch::MirPatch;
@@ -97,8 +97,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
&simplify::SimplifyCfg::new("make_shim"),
&add_call_guards::CriticalCallEdges,
&abort_unwinding_calls::AbortUnwindingCalls,
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)),
],
+ Some(MirPhase::Runtime(RuntimePhase::Optimized)),
);
debug!("make_shim({:?}) = {:?}", instance, result);
@@ -312,7 +312,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
let param_env = tcx.param_env(def_id);
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
- let is_copy = self_ty.is_copy_modulo_regions(tcx.at(builder.span), param_env);
+ let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
let dest = Place::return_place();
let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0)));