mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 12:36:35 +03:00
use deref_patterns in rustc_mir_transform
This commit is contained in:
@@ -95,7 +95,7 @@ fn should_lint_const_item_usage(
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
|
||||
fn visit_statement(&mut self, stmt: &Statement<'tcx>, loc: Location) {
|
||||
if let StatementKind::Assign(box (lhs, _)) = &stmt.kind {
|
||||
if let StatementKind::Assign((lhs, _)) = &stmt.kind {
|
||||
// Check for assignment to fields of a constant
|
||||
// Assigning directly to a constant (e.g. `FOO = true;`) is a hard error,
|
||||
// so emitting a lint would be redundant.
|
||||
|
||||
@@ -31,7 +31,7 @@ fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
for statement in basic_block.statements.iter_mut() {
|
||||
match statement.kind {
|
||||
StatementKind::AscribeUserType(..)
|
||||
| StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake(_), _)))
|
||||
| StatementKind::Assign((_, Rvalue::Ref(_, BorrowKind::Fake(_), _)))
|
||||
| StatementKind::Coverage(
|
||||
// These kinds of coverage statements are markers inserted during
|
||||
// MIR building, and are not needed after InstrumentCoverage.
|
||||
@@ -41,7 +41,7 @@ fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
| StatementKind::BackwardIncompatibleDropHint { .. } => {
|
||||
statement.make_nop(true)
|
||||
}
|
||||
StatementKind::Assign(box (
|
||||
StatementKind::Assign((
|
||||
_,
|
||||
Rvalue::Cast(
|
||||
ref mut cast_kind @ CastKind::PointerCoercion(
|
||||
|
||||
@@ -151,7 +151,7 @@ fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) {
|
||||
self.super_statement(stmt, loc);
|
||||
|
||||
// Do not leave tautological assignments around.
|
||||
if let StatementKind::Assign(box (lhs, ref rhs)) = stmt.kind
|
||||
if let StatementKind::Assign((lhs, ref rhs)) = stmt.kind
|
||||
&& let Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _) = *rhs
|
||||
&& lhs == rhs
|
||||
{
|
||||
|
||||
@@ -997,12 +997,10 @@ fn compute_layout<'tcx>(
|
||||
let ignore_for_traits = match decl.local_info {
|
||||
// Do not include raw pointers created from accessing `static` items, as those could
|
||||
// well be re-created by another access to the same static.
|
||||
ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => {
|
||||
!is_thread_local
|
||||
}
|
||||
ClearCrossCrate::Set(LocalInfo::StaticRef { is_thread_local, .. }) => !is_thread_local,
|
||||
// Fake borrows are only read by fake reads, so do not have any reality in
|
||||
// post-analysis MIR.
|
||||
ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true,
|
||||
ClearCrossCrate::Set(LocalInfo::FakeBorrow) => true,
|
||||
_ => false,
|
||||
};
|
||||
let decl =
|
||||
@@ -1747,7 +1745,7 @@ fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location:
|
||||
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (lhs, rhs)) => {
|
||||
StatementKind::Assign((lhs, rhs)) => {
|
||||
self.check_assigned_place(*lhs, |this| this.visit_rvalue(rhs, location));
|
||||
}
|
||||
|
||||
|
||||
@@ -346,7 +346,7 @@ fn visit_statement(&mut self, statement: &mut mir::Statement<'tcx>, location: mi
|
||||
// here at all since they're fully a MIR borrowck artifact, and we
|
||||
// don't need to borrowck by-move MIR bodies. But it's best to preserve
|
||||
// as much as we can between these two bodies :)
|
||||
if let mir::StatementKind::Assign(box (_, rvalue)) = &statement.kind
|
||||
if let mir::StatementKind::Assign((_, rvalue)) = &statement.kind
|
||||
&& let mir::Rvalue::Ref(_, mir::BorrowKind::Fake(mir::FakeBorrowKind::Shallow), place) =
|
||||
rvalue
|
||||
&& let mir::PlaceRef {
|
||||
|
||||
@@ -80,7 +80,7 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
|
||||
// and `_1` is the `Place` for `somenum`.
|
||||
//
|
||||
// If and when the Issue is resolved, remove this special case match pattern:
|
||||
StatementKind::FakeRead(box (FakeReadCause::ForGuardBinding, _)) => None,
|
||||
StatementKind::FakeRead((FakeReadCause::ForGuardBinding, _)) => None,
|
||||
|
||||
// Retain spans from most other statements.
|
||||
StatementKind::FakeRead(_)
|
||||
|
||||
@@ -164,13 +164,13 @@ fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
|
||||
|
||||
fn handle_statement(&self, statement: &Statement<'tcx>, state: &mut State<FlatSet<Scalar>>) {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (place, rvalue)) => {
|
||||
StatementKind::Assign((place, rvalue)) => {
|
||||
self.handle_assign(*place, rvalue, state);
|
||||
}
|
||||
StatementKind::SetDiscriminant { box place, variant_index } => {
|
||||
self.handle_set_discriminant(*place, *variant_index, state);
|
||||
StatementKind::SetDiscriminant { place, variant_index } => {
|
||||
self.handle_set_discriminant(**place, *variant_index, state);
|
||||
}
|
||||
StatementKind::Intrinsic(box intrinsic) => {
|
||||
StatementKind::Intrinsic(intrinsic) => {
|
||||
self.handle_intrinsic(intrinsic);
|
||||
}
|
||||
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
|
||||
@@ -214,7 +214,7 @@ fn handle_operand(
|
||||
) -> ValueOrPlace<FlatSet<Scalar>> {
|
||||
match operand {
|
||||
Operand::RuntimeChecks(_) => ValueOrPlace::TOP,
|
||||
Operand::Constant(box constant) => {
|
||||
Operand::Constant(constant) => {
|
||||
ValueOrPlace::Value(self.handle_constant(constant, state))
|
||||
}
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
@@ -352,7 +352,7 @@ fn handle_assign(
|
||||
}
|
||||
}
|
||||
}
|
||||
Rvalue::BinaryOp(op, box (left, right)) if op.is_overflowing() => {
|
||||
Rvalue::BinaryOp(op, (left, right)) if op.is_overflowing() => {
|
||||
// Flood everything now, so we can use `insert_value_idx` directly later.
|
||||
state.flood(target.as_ref(), &self.map);
|
||||
|
||||
@@ -442,7 +442,7 @@ fn handle_rvalue(
|
||||
FlatSet::Top => FlatSet::Top,
|
||||
}
|
||||
}
|
||||
Rvalue::BinaryOp(op, box (left, right)) if !op.is_overflowing() => {
|
||||
Rvalue::BinaryOp(op, (left, right)) if !op.is_overflowing() => {
|
||||
// Overflows must be ignored here.
|
||||
// The overflowing operators are handled in `handle_assign`.
|
||||
let (val, _overflow) = self.binary_op(state, *op, left, right);
|
||||
@@ -546,7 +546,7 @@ fn assign_operand(
|
||||
self.assign_constant(state, place, op, rhs.projection);
|
||||
}
|
||||
}
|
||||
Operand::Constant(box constant) => {
|
||||
Operand::Constant(constant) => {
|
||||
if let Some(constant) = self
|
||||
.ecx
|
||||
.borrow()
|
||||
@@ -956,7 +956,7 @@ fn visit_after_early_statement_effect(
|
||||
location: Location,
|
||||
) {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (_, rvalue)) => {
|
||||
StatementKind::Assign((_, rvalue)) => {
|
||||
OperandCollector {
|
||||
state,
|
||||
visitor: self,
|
||||
@@ -978,10 +978,10 @@ fn visit_after_primary_statement_effect(
|
||||
location: Location,
|
||||
) {
|
||||
match statement.kind {
|
||||
StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(_), _))) => {
|
||||
StatementKind::Assign((_, Rvalue::Use(Operand::Constant(_), _))) => {
|
||||
// Don't overwrite the assignment if it already uses a constant (to keep the span).
|
||||
}
|
||||
StatementKind::Assign(box (place, _)) => {
|
||||
StatementKind::Assign((place, _)) => {
|
||||
if let Some(value) = self.try_make_constant(
|
||||
&mut analysis.ecx.borrow_mut(),
|
||||
place,
|
||||
@@ -1020,7 +1020,7 @@ fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
|
||||
if let Some(value) = self.assignments.get(&location) {
|
||||
match &mut statement.kind {
|
||||
StatementKind::Assign(box (_, rvalue)) => {
|
||||
StatementKind::Assign((_, rvalue)) => {
|
||||
let old_retag = match rvalue {
|
||||
Rvalue::Use(_, retag) => *retag,
|
||||
_ => WithRetag::Yes,
|
||||
|
||||
@@ -282,7 +282,7 @@ fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Locatio
|
||||
};
|
||||
self.super_statement(statement, location);
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (dest, rvalue)) => {
|
||||
StatementKind::Assign((dest, rvalue)) => {
|
||||
match rvalue {
|
||||
Rvalue::Use(Operand::Copy(place) | Operand::Move(place), _) => {
|
||||
// These might've been turned into self-assignments by the replacement
|
||||
@@ -396,10 +396,8 @@ struct FindAssignments<'a, 'tcx> {
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
|
||||
if let StatementKind::Assign(box (
|
||||
lhs,
|
||||
Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _),
|
||||
)) = &statement.kind
|
||||
if let StatementKind::Assign((lhs, Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _))) =
|
||||
&statement.kind
|
||||
&& let Some(src) = lhs.as_local()
|
||||
&& let Some(dest) = rhs.as_local()
|
||||
{
|
||||
@@ -571,7 +569,7 @@ fn save_as_intervals<'tcx>(
|
||||
// We make an exception for simple assignments `_a.stuff = {copy|move} _b.stuff`,
|
||||
// as marking `_b` live here would prevent unification.
|
||||
let is_simple_assignment = match stmt.kind {
|
||||
StatementKind::Assign(box (
|
||||
StatementKind::Assign((
|
||||
lhs,
|
||||
Rvalue::CopyForDeref(rhs)
|
||||
| Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _),
|
||||
|
||||
@@ -303,8 +303,7 @@ fn evaluate_candidate<'tcx>(
|
||||
// ```
|
||||
let [
|
||||
Statement {
|
||||
kind: StatementKind::Assign(box (_, Rvalue::Discriminant(child_place))),
|
||||
..
|
||||
kind: StatementKind::Assign((_, Rvalue::Discriminant(child_place))), ..
|
||||
},
|
||||
] = bbs[child].statements.as_slice()
|
||||
else {
|
||||
@@ -368,8 +367,7 @@ fn verify_candidate_branch<'tcx>(
|
||||
return false;
|
||||
};
|
||||
// The statement must assign the discriminant of `place`.
|
||||
let StatementKind::Assign(box (discr_place, Rvalue::Discriminant(from_place))) =
|
||||
statement.kind
|
||||
let StatementKind::Assign((discr_place, Rvalue::Discriminant(from_place))) = statement.kind
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -1101,7 +1101,7 @@ fn simplify_rvalue(
|
||||
Rvalue::Cast(ref mut kind, ref mut value, to) => {
|
||||
return self.simplify_cast(kind, value, to, location);
|
||||
}
|
||||
Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => {
|
||||
Rvalue::BinaryOp(op, (ref mut lhs, ref mut rhs)) => {
|
||||
return self.simplify_binary(op, lhs, rhs, location);
|
||||
}
|
||||
Rvalue::UnaryOp(op, ref mut arg_op) => {
|
||||
@@ -1200,7 +1200,7 @@ fn simplify_aggregate(
|
||||
let tcx = self.tcx;
|
||||
let ty = rvalue.ty(self.local_decls, tcx);
|
||||
|
||||
let Rvalue::Aggregate(box ref kind, ref mut field_ops) = *rvalue else { bug!() };
|
||||
let Rvalue::Aggregate(ref kind, ref mut field_ops) = *rvalue else { bug!() };
|
||||
|
||||
if field_ops.is_empty() {
|
||||
let is_zst = match *kind {
|
||||
|
||||
@@ -41,7 +41,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
};
|
||||
for block in body.basic_blocks.as_mut() {
|
||||
for statement in block.statements.iter_mut() {
|
||||
let StatementKind::Assign(box (.., rvalue)) = &mut statement.kind else {
|
||||
let StatementKind::Assign((.., rvalue)) = &mut statement.kind else {
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
|
||||
/// GVN can also do this optimization, but GVN is only run at mir-opt-level 2 so having this in
|
||||
/// InstSimplify helps unoptimized builds.
|
||||
fn simplify_repeated_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
|
||||
let Rvalue::Aggregate(box AggregateKind::Array(_), fields) = &*rvalue else {
|
||||
let Rvalue::Aggregate(AggregateKind::Array(_), fields) = &*rvalue else {
|
||||
return;
|
||||
};
|
||||
if fields.len() < 5 {
|
||||
@@ -106,7 +106,7 @@ fn simplify_repeated_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
|
||||
|
||||
/// Transform boolean comparisons into logical operations.
|
||||
fn simplify_bool_cmp(&self, rvalue: &mut Rvalue<'tcx>) {
|
||||
let Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) = &*rvalue else { return };
|
||||
let Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), (a, b)) = &*rvalue else { return };
|
||||
*rvalue = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
|
||||
// Transform "Eq(a, true)" ==> "a"
|
||||
(BinOp::Eq, _, Some(true)) => Rvalue::Use(a.clone(), WithRetag::Yes),
|
||||
@@ -170,7 +170,7 @@ fn simplify_ref_deref(&self, rvalue: &mut Rvalue<'tcx>) {
|
||||
|
||||
/// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`.
|
||||
fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
|
||||
if let Rvalue::Aggregate(box AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue
|
||||
if let Rvalue::Aggregate(AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue
|
||||
&& let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx)
|
||||
&& meta_ty.is_unit()
|
||||
{
|
||||
|
||||
@@ -396,16 +396,16 @@ fn mutated_statement(
|
||||
stmt: &Statement<'tcx>,
|
||||
) -> Option<(Place<'tcx>, Option<TrackElem>)> {
|
||||
match stmt.kind {
|
||||
StatementKind::Assign(box (place, _)) => Some((place, None)),
|
||||
StatementKind::SetDiscriminant { box place, variant_index: _ } => {
|
||||
Some((place, Some(TrackElem::Discriminant)))
|
||||
StatementKind::Assign((place, _)) => Some((place, None)),
|
||||
StatementKind::SetDiscriminant { ref place, variant_index: _ } => {
|
||||
Some((**place, Some(TrackElem::Discriminant)))
|
||||
}
|
||||
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
|
||||
Some((Place::from(local), None))
|
||||
}
|
||||
| StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(..))
|
||||
| StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(..))
|
||||
// copy_nonoverlapping takes pointers and mutated the pointed-to value.
|
||||
| StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(..))
|
||||
| StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping(..))
|
||||
| StatementKind::AscribeUserType(..)
|
||||
| StatementKind::Coverage(..)
|
||||
| StatementKind::FakeRead(..)
|
||||
@@ -518,7 +518,7 @@ fn process_assign(
|
||||
self.process_copy(lhs, rhs, state)
|
||||
}
|
||||
// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
|
||||
Rvalue::Aggregate(box kind, operands) => {
|
||||
Rvalue::Aggregate(kind, operands) => {
|
||||
let agg_ty = lhs_place.ty(self.body, self.tcx).ty;
|
||||
let lhs = match kind {
|
||||
// Do not support unions.
|
||||
@@ -573,8 +573,8 @@ fn process_assign(
|
||||
// Create a condition on `rhs ?= B`.
|
||||
Rvalue::BinaryOp(
|
||||
op,
|
||||
box (Operand::Move(operand) | Operand::Copy(operand), Operand::Constant(value))
|
||||
| box (Operand::Constant(value), Operand::Move(operand) | Operand::Copy(operand)),
|
||||
(Operand::Move(operand) | Operand::Copy(operand), Operand::Constant(value))
|
||||
| (Operand::Constant(value), Operand::Move(operand) | Operand::Copy(operand)),
|
||||
) => {
|
||||
let equals = match op {
|
||||
BinOp::Eq => ScalarInt::TRUE,
|
||||
@@ -617,8 +617,8 @@ fn process_statement(&mut self, stmt: &Statement<'tcx>, state: &mut ConditionSet
|
||||
match &stmt.kind {
|
||||
// If we expect `discriminant(place) ?= A`,
|
||||
// we have an opportunity if `variant_index ?= A`.
|
||||
StatementKind::SetDiscriminant { box place, variant_index } => {
|
||||
let Some(discr_target) = self.place(*place, Some(TrackElem::Discriminant)) else {
|
||||
StatementKind::SetDiscriminant { place, variant_index } => {
|
||||
let Some(discr_target) = self.place(**place, Some(TrackElem::Discriminant)) else {
|
||||
return;
|
||||
};
|
||||
let enum_ty = place.ty(self.body, self.tcx).ty;
|
||||
@@ -633,15 +633,13 @@ fn process_statement(&mut self, stmt: &Statement<'tcx>, state: &mut ConditionSet
|
||||
self.process_immediate(discr_target, discr, state)
|
||||
}
|
||||
// If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`.
|
||||
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(
|
||||
StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(
|
||||
Operand::Copy(place) | Operand::Move(place),
|
||||
)) => {
|
||||
let Some(place) = self.place_value(*place, None) else { return };
|
||||
state.fulfill_matches(place, ScalarInt::TRUE);
|
||||
}
|
||||
StatementKind::Assign(box (lhs_place, rhs)) => {
|
||||
self.process_assign(lhs_place, rhs, state)
|
||||
}
|
||||
StatementKind::Assign((lhs_place, rhs)) => self.process_assign(lhs_place, rhs, state),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +415,7 @@ fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) -> Option<
|
||||
trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
|
||||
self.check_unary_op(*op, arg, location)?;
|
||||
}
|
||||
Rvalue::BinaryOp(op, box (left, right)) => {
|
||||
Rvalue::BinaryOp(op, (left, right)) => {
|
||||
trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
|
||||
self.check_binary_op(*op, left, right, location)?;
|
||||
}
|
||||
@@ -555,7 +555,7 @@ fn eval_rvalue(&mut self, rvalue: &Rvalue<'tcx>, dest: &Place<'tcx>) -> Option<(
|
||||
|
||||
CopyForDeref(place) | Reborrow(_, _, place) => self.eval_place(place)?.into(),
|
||||
|
||||
BinaryOp(bin_op, box (ref left, ref right)) => {
|
||||
BinaryOp(bin_op, (ref left, ref right)) => {
|
||||
let left = self.eval_operand(left)?;
|
||||
let left = self.use_ecx(|this| this.ecx.read_immediate(&left))?;
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
|
||||
for (block, data) in body.basic_blocks.as_mut().iter_enumerated_mut() {
|
||||
for (statement_index, st) in data.statements.iter_mut().enumerate() {
|
||||
let StatementKind::Assign(box (
|
||||
let StatementKind::Assign((
|
||||
lhs,
|
||||
Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _),
|
||||
)) = &st.kind
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// tidy-alphabetical-start
|
||||
#![feature(box_patterns)]
|
||||
#![feature(const_type_name)]
|
||||
#![feature(cow_is_borrowed)]
|
||||
#![feature(deref_patterns)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![feature(iterator_try_collect)]
|
||||
#![feature(try_blocks)]
|
||||
@@ -241,7 +241,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
|
||||
let terminator = bb.terminator.as_mut().expect("invalid terminator");
|
||||
match terminator.kind {
|
||||
TerminatorKind::Call {
|
||||
func: Operand::Constant(box ConstOperand { ref const_, .. }),
|
||||
func: Operand::Constant(ConstOperand { ref const_, .. }),
|
||||
ref mut args,
|
||||
destination,
|
||||
target,
|
||||
|
||||
@@ -84,7 +84,7 @@ fn visit_local(&mut self, local: Local, context: PlaceContext, location: Locatio
|
||||
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (dest, rvalue)) => {
|
||||
StatementKind::Assign((dest, rvalue)) => {
|
||||
let forbid_aliasing = match rvalue {
|
||||
Rvalue::Use(..)
|
||||
| Rvalue::CopyForDeref(..)
|
||||
|
||||
@@ -369,12 +369,12 @@ fn find_self_assignments<'tcx>(
|
||||
|
||||
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
|
||||
for (statement_index, stmt) in bb_data.statements.iter().enumerate() {
|
||||
let StatementKind::Assign(box (first_place, rvalue)) = &stmt.kind else { continue };
|
||||
let StatementKind::Assign((first_place, rvalue)) = &stmt.kind else { continue };
|
||||
match rvalue {
|
||||
// For checked binary ops, the MIR builder inserts an assertion in between.
|
||||
Rvalue::BinaryOp(
|
||||
BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow,
|
||||
box (Operand::Copy(lhs), _),
|
||||
(Operand::Copy(lhs), _),
|
||||
) => {
|
||||
// Checked binary ops only appear at the end of the block, before the assertion.
|
||||
if statement_index + 1 != bb_data.statements.len() {
|
||||
@@ -382,10 +382,7 @@ fn find_self_assignments<'tcx>(
|
||||
}
|
||||
|
||||
let TerminatorKind::Assert {
|
||||
cond,
|
||||
target,
|
||||
msg: box AssertKind::Overflow(..),
|
||||
..
|
||||
cond, target, msg: AssertKind::Overflow(..), ..
|
||||
} = &bb_data.terminator().kind
|
||||
else {
|
||||
continue;
|
||||
@@ -393,7 +390,7 @@ fn find_self_assignments<'tcx>(
|
||||
let Some(assign) = body.basic_blocks[*target].statements.first() else {
|
||||
continue;
|
||||
};
|
||||
let StatementKind::Assign(box (dest, Rvalue::Use(Operand::Move(temp), _))) =
|
||||
let StatementKind::Assign((dest, Rvalue::Use(Operand::Move(temp), _))) =
|
||||
assign.kind
|
||||
else {
|
||||
continue;
|
||||
@@ -437,7 +434,7 @@ fn find_self_assignments<'tcx>(
|
||||
}
|
||||
}
|
||||
// Straight self-assignment.
|
||||
Rvalue::BinaryOp(op, box (Operand::Copy(lhs), _)) => {
|
||||
Rvalue::BinaryOp(op, (Operand::Copy(lhs), _)) => {
|
||||
if lhs != first_place {
|
||||
continue;
|
||||
}
|
||||
@@ -724,8 +721,7 @@ fn find_dead_assignments(
|
||||
let live = cursor.get();
|
||||
ever_live.union(live);
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (place, _))
|
||||
| StatementKind::SetDiscriminant { box place, .. } => {
|
||||
StatementKind::Assign((place, _)) => {
|
||||
check_place(
|
||||
*place,
|
||||
AccessKind::Assign,
|
||||
@@ -734,6 +730,15 @@ fn find_dead_assignments(
|
||||
live,
|
||||
);
|
||||
}
|
||||
StatementKind::SetDiscriminant { place, .. } => {
|
||||
check_place(
|
||||
**place,
|
||||
AccessKind::Assign,
|
||||
statement.source_info,
|
||||
location,
|
||||
live,
|
||||
);
|
||||
}
|
||||
StatementKind::StorageLive(_)
|
||||
| StatementKind::StorageDead(_)
|
||||
| StatementKind::Coverage(_)
|
||||
@@ -1299,17 +1304,17 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
match statement.kind {
|
||||
// `ForLet(None)` and `ForGuardBinding` fake reads erroneously mark the just-assigned
|
||||
// locals as live. This defeats the purpose of the analysis for such bindings.
|
||||
StatementKind::FakeRead(box (
|
||||
StatementKind::FakeRead((
|
||||
FakeReadCause::ForLet(None) | FakeReadCause::ForGuardBinding,
|
||||
_,
|
||||
)) => return,
|
||||
// Handle self-assignment by restricting the read/write they do.
|
||||
StatementKind::Assign(box (ref dest, ref rvalue))
|
||||
StatementKind::Assign((ref dest, ref rvalue))
|
||||
if self.self_assignment.contains(&location) =>
|
||||
{
|
||||
if let Rvalue::BinaryOp(
|
||||
BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow,
|
||||
box (_, rhs),
|
||||
(_, rhs),
|
||||
) = rvalue
|
||||
{
|
||||
// We are computing the binary operation:
|
||||
@@ -1321,7 +1326,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Store),
|
||||
location,
|
||||
);
|
||||
} else if let Rvalue::BinaryOp(_, box (_, rhs)) = rvalue {
|
||||
} else if let Rvalue::BinaryOp(_, (_, rhs)) = rvalue {
|
||||
// We are computing the binary operation:
|
||||
// - the LHS is being updated, so we don't read it;
|
||||
// - the RHS still needs to be read.
|
||||
@@ -1371,7 +1376,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||
// captures as live in the surrounding function. This allows to report unused variables,
|
||||
// even if they have been (uselessly) captured.
|
||||
Rvalue::Aggregate(
|
||||
box AggregateKind::Closure(def_id, _) | box AggregateKind::Coroutine(def_id, _),
|
||||
AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _),
|
||||
operands,
|
||||
) => {
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
|
||||
@@ -240,7 +240,7 @@ fn unify_by_copy(
|
||||
// _2 = discriminant(*_1); // "*_1" is the expected the copy source.
|
||||
// switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
|
||||
let &Statement {
|
||||
kind: StatementKind::Assign(box (discr_place, Rvalue::Discriminant(copy_src_place))),
|
||||
kind: StatementKind::Assign((discr_place, Rvalue::Discriminant(copy_src_place))),
|
||||
..
|
||||
} = bbs[self.switch_bb].statements.last()?
|
||||
else {
|
||||
@@ -264,7 +264,7 @@ fn unify_by_copy(
|
||||
for &(case, rvalue) in rvals.iter() {
|
||||
match rvalue {
|
||||
// Check if `_3 = const Foo::B` can be transformed to `_3 = copy *_1`.
|
||||
Rvalue::Use(Operand::Constant(box constant), _)
|
||||
Rvalue::Use(Operand::Constant(constant), _)
|
||||
if let Const::Val(const_, ty) = constant.const_ =>
|
||||
{
|
||||
let (ecx, op) = mk_eval_cx_for_const_val(
|
||||
@@ -284,7 +284,7 @@ fn unify_by_copy(
|
||||
}
|
||||
Rvalue::Use(Operand::Copy(src_place), _) if *src_place == copy_src_place => {}
|
||||
// Check if `_3 = Foo::B` can be transformed to `_3 = copy *_1`.
|
||||
Rvalue::Aggregate(box AggregateKind::Adt(_, variant_index, _, _, None), fields)
|
||||
Rvalue::Aggregate(AggregateKind::Adt(_, variant_index, _, _, None), fields)
|
||||
if fields.is_empty()
|
||||
&& let Some(Discr { val, .. }) =
|
||||
src_ty.ty.discriminant_for_variant(self.tcx, *variant_index)
|
||||
@@ -510,18 +510,18 @@ fn candidate_const<'tcx, 'a>(
|
||||
) -> Option<(Vec<(u128, &'a ConstOperand<'tcx>)>, Option<&'a ConstOperand<'tcx>>)> {
|
||||
// We ignore the retag mode here, which means the `Use` we insert later must be without retag.
|
||||
let otherwise = if let Some(otherwise) = otherwise {
|
||||
let Rvalue::Use(Operand::Constant(box const_), _) = otherwise else {
|
||||
let Rvalue::Use(Operand::Constant(const_), _) = otherwise else {
|
||||
return None;
|
||||
};
|
||||
Some(const_)
|
||||
Some(&**const_)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let consts = rvals
|
||||
.into_iter()
|
||||
.map(|&(case, rval)| {
|
||||
let Rvalue::Use(Operand::Constant(box const_), _) = rval else { return None };
|
||||
Some((case, const_))
|
||||
let Rvalue::Use(Operand::Constant(const_), _) = rval else { return None };
|
||||
Some((case, &**const_))
|
||||
})
|
||||
.try_collect()?;
|
||||
Some((consts, otherwise))
|
||||
|
||||
@@ -461,7 +461,7 @@ fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable>
|
||||
self.validate_operand(operand)?;
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(op, box (lhs, rhs)) => {
|
||||
Rvalue::BinaryOp(op, (lhs, rhs)) => {
|
||||
let op = *op;
|
||||
let lhs_ty = lhs.ty(self.body, self.tcx);
|
||||
|
||||
@@ -796,7 +796,7 @@ fn promote_temp(&mut self, temp: Local) -> Local {
|
||||
if loc.statement_index < num_stmts {
|
||||
let (mut rvalue, source_info) = {
|
||||
let statement = &mut self.source[loc.block].statements[loc.statement_index];
|
||||
let StatementKind::Assign(box (_, rhs)) = &mut statement.kind else {
|
||||
let StatementKind::Assign((_, rhs)) = &mut statement.kind else {
|
||||
span_bug!(statement.source_info.span, "{:?} is not an assignment", statement);
|
||||
};
|
||||
|
||||
@@ -901,7 +901,7 @@ fn promote_candidate(
|
||||
let local_decls = &mut self.source.local_decls;
|
||||
let loc = candidate.location;
|
||||
let statement = &mut blocks[loc.block].statements[loc.statement_index];
|
||||
let StatementKind::Assign(box (_, Rvalue::Ref(region, borrow_kind, place))) =
|
||||
let StatementKind::Assign((_, Rvalue::Ref(region, borrow_kind, place))) =
|
||||
&mut statement.kind
|
||||
else {
|
||||
bug!()
|
||||
@@ -1013,7 +1013,7 @@ fn promote_candidates<'tcx>(
|
||||
let mut extra_statements = vec![];
|
||||
for candidate in candidates.into_iter().rev() {
|
||||
let Location { block, statement_index } = candidate.location;
|
||||
if let StatementKind::Assign(box (place, _)) = &body[block].statements[statement_index].kind
|
||||
if let StatementKind::Assign((place, _)) = &body[block].statements[statement_index].kind
|
||||
&& let Some(local) = place.as_local()
|
||||
{
|
||||
if temps[local] == TempState::PromotedOut {
|
||||
@@ -1069,7 +1069,7 @@ fn promote_candidates<'tcx>(
|
||||
let promoted = |index: Local| temps[index] == TempState::PromotedOut;
|
||||
for block in body.basic_blocks_mut() {
|
||||
block.retain_statements(|statement| match &statement.kind {
|
||||
StatementKind::Assign(box (place, _)) => {
|
||||
StatementKind::Assign((place, _)) => {
|
||||
if let Some(index) = place.as_local() {
|
||||
!promoted(index)
|
||||
} else {
|
||||
|
||||
@@ -102,7 +102,7 @@ fn is_nop_landing_pad(
|
||||
// These are all noops in a landing pad
|
||||
}
|
||||
|
||||
StatementKind::Assign(box (place, Rvalue::Use(..) | Rvalue::Discriminant(_))) => {
|
||||
StatementKind::Assign((place, Rvalue::Use(..) | Rvalue::Discriminant(_))) => {
|
||||
if place.as_local().is_some() {
|
||||
// Writing to a local (e.g., a drop flag) does not
|
||||
// turn a landing pad to a non-nop
|
||||
|
||||
@@ -119,13 +119,14 @@ fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _: Location) {
|
||||
|
||||
fn visit_statement(&mut self, statement: &mut Statement<'tcx>, loc: Location) {
|
||||
let place_for_ty = match statement.kind {
|
||||
StatementKind::Assign(box (place, ref rvalue)) => {
|
||||
StatementKind::Assign((place, ref rvalue)) => {
|
||||
rvalue.is_safe_to_remove().then_some(place)
|
||||
}
|
||||
StatementKind::SetDiscriminant { box place, variant_index: _ }
|
||||
| StatementKind::AscribeUserType(box (place, _), _)
|
||||
| StatementKind::PlaceMention(box place)
|
||||
| StatementKind::FakeRead(box (_, place)) => Some(place),
|
||||
StatementKind::SetDiscriminant { ref place, variant_index: _ }
|
||||
| StatementKind::PlaceMention(ref place) => Some(**place),
|
||||
StatementKind::AscribeUserType((place, _), _) | StatementKind::FakeRead((_, place)) => {
|
||||
Some(place)
|
||||
}
|
||||
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
|
||||
Some(local.into())
|
||||
}
|
||||
|
||||
@@ -579,7 +579,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
| StatementKind::Nop
|
||||
| StatementKind::StorageLive(..)
|
||||
| StatementKind::StorageDead(..) => {}
|
||||
StatementKind::Assign(box (ref place, ref rvalue)) => {
|
||||
StatementKind::Assign((ref place, ref rvalue)) => {
|
||||
if rvalue.is_safe_to_remove() {
|
||||
self.visit_lhs(place, location);
|
||||
self.visit_rvalue(rvalue, location);
|
||||
@@ -626,9 +626,9 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod
|
||||
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
|
||||
used_locals.is_used(*local)
|
||||
}
|
||||
StatementKind::Assign(box (place, _))
|
||||
| StatementKind::SetDiscriminant { box place, .. }
|
||||
| StatementKind::BackwardIncompatibleDropHint { box place, .. } => {
|
||||
StatementKind::Assign((place, _)) => used_locals.is_used(place.local),
|
||||
StatementKind::SetDiscriminant { place, .. }
|
||||
| StatementKind::BackwardIncompatibleDropHint { place, .. } => {
|
||||
used_locals.is_used(place.local)
|
||||
}
|
||||
_ => continue,
|
||||
|
||||
@@ -51,7 +51,7 @@ fn try_get_const<'tcx, 'a>(
|
||||
for (statement_index, stmt) in block.statements.iter().enumerate() {
|
||||
let has_place_const = pre_place_const.take();
|
||||
// Simplify `assume` of a known value: either a NOP or unreachable.
|
||||
if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind
|
||||
if let StatementKind::Intrinsic(ref intrinsic) = stmt.kind
|
||||
&& let NonDivergingIntrinsic::Assume(discr) = intrinsic
|
||||
&& let Some(c) = try_get_const(discr, has_place_const)
|
||||
&& let Some(constant) = c.const_.try_eval_bool(tcx, typing_env)
|
||||
@@ -62,7 +62,7 @@ fn try_get_const<'tcx, 'a>(
|
||||
patch.patch_terminator(bb, TerminatorKind::Unreachable);
|
||||
continue 'blocks;
|
||||
}
|
||||
} else if let StatementKind::Assign(box (lhs, ref rvalue)) = stmt.kind
|
||||
} else if let StatementKind::Assign((lhs, ref rvalue)) = stmt.kind
|
||||
&& let Rvalue::Use(Operand::Constant(c), _) = rvalue
|
||||
{
|
||||
pre_place_const = Some((lhs, c));
|
||||
|
||||
@@ -92,10 +92,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
|
||||
use Operand::*;
|
||||
match rhs {
|
||||
Rvalue::BinaryOp(_, box (left @ Move(_), Constant(_))) => {
|
||||
Rvalue::BinaryOp(_, (left @ Move(_), Constant(_))) => {
|
||||
*left = Copy(opt.to_switch_on);
|
||||
}
|
||||
Rvalue::BinaryOp(_, box (Constant(_), right @ Move(_))) => {
|
||||
Rvalue::BinaryOp(_, (Constant(_), right @ Move(_))) => {
|
||||
*right = Copy(opt.to_switch_on);
|
||||
}
|
||||
_ => (),
|
||||
@@ -173,14 +173,11 @@ fn find_optimizations(&self, ssa: &SsaLocals) -> Vec<OptimizationInfo<'tcx>> {
|
||||
// find the statement that assigns the place being switched on
|
||||
bb.statements.iter().enumerate().rev().find_map(|(stmt_idx, stmt)| {
|
||||
match &stmt.kind {
|
||||
rustc_middle::mir::StatementKind::Assign(box (lhs, rhs))
|
||||
rustc_middle::mir::StatementKind::Assign((lhs, rhs))
|
||||
if *lhs == place_switched_on =>
|
||||
{
|
||||
match rhs {
|
||||
Rvalue::BinaryOp(
|
||||
op @ (BinOp::Eq | BinOp::Ne),
|
||||
box (left, right),
|
||||
) => {
|
||||
Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), (left, right)) => {
|
||||
let (branch_value_scalar, branch_value_ty, to_switch_on) =
|
||||
find_branch_value_info(left, right, ssa)?;
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@ fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Locatio
|
||||
// a_1 = y
|
||||
// ...
|
||||
// ```
|
||||
StatementKind::Assign(box (place, Rvalue::Aggregate(_, ref mut operands))) => {
|
||||
StatementKind::Assign((place, Rvalue::Aggregate(_, ref mut operands))) => {
|
||||
if let Some(local) = place.as_local()
|
||||
&& let Some(final_locals) = &self.replacements.fragments[local]
|
||||
{
|
||||
@@ -368,7 +368,7 @@ fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Locatio
|
||||
// ...
|
||||
// ```
|
||||
// ConstProp will pick up the pieces and replace them by actual constants.
|
||||
StatementKind::Assign(box (place, Rvalue::Use(Operand::Constant(_), retag))) => {
|
||||
StatementKind::Assign((place, Rvalue::Use(Operand::Constant(_), retag))) => {
|
||||
if let Some(final_locals) = self.replacements.place_fragments(place) {
|
||||
// Put the deaggregated statements *after* the original one.
|
||||
let location = location.successor_within_block();
|
||||
@@ -392,7 +392,7 @@ fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Locatio
|
||||
// a_1 = move? place.1
|
||||
// ...
|
||||
// ```
|
||||
StatementKind::Assign(box (
|
||||
StatementKind::Assign((
|
||||
lhs,
|
||||
Rvalue::Use(ref op @ (Operand::Copy(rplace) | Operand::Move(rplace)), retag),
|
||||
)) => {
|
||||
|
||||
@@ -426,7 +426,7 @@ fn apply_primary_statement_effect(
|
||||
) {
|
||||
match statement.kind {
|
||||
// An assignment makes a local initialized.
|
||||
StatementKind::Assign(box (place, _)) => {
|
||||
StatementKind::Assign((place, _)) => {
|
||||
if let Some(local) = place.as_local() {
|
||||
state.remove(local);
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
|
||||
fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
|
||||
self.super_statement(statement, location);
|
||||
match &statement.kind {
|
||||
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(operand))
|
||||
StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(operand))
|
||||
if let Some(place) = operand.place()
|
||||
&& self.is_ssa(place) =>
|
||||
{
|
||||
|
||||
@@ -82,7 +82,7 @@ pub(crate) fn trivial_const<'a, 'tcx: 'a, F, B>(
|
||||
return None;
|
||||
}
|
||||
|
||||
let StatementKind::Assign(box (place, rvalue)) = &block.statements[0].kind else {
|
||||
let StatementKind::Assign((place, rvalue)) = &block.statements[0].kind else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ fn get_switched_on_type<'tcx>(
|
||||
|
||||
let stmt_before_term = block_data.statements.last()?;
|
||||
|
||||
if let StatementKind::Assign(box (l, Rvalue::Discriminant(place))) = stmt_before_term.kind
|
||||
if let StatementKind::Assign((l, Rvalue::Discriminant(place))) = stmt_before_term.kind
|
||||
&& l.as_local() == Some(local)
|
||||
{
|
||||
let ty = place.ty(body, tcx).ty;
|
||||
|
||||
@@ -899,7 +899,7 @@ fn visit_projection_elem(
|
||||
}
|
||||
|
||||
fn visit_var_debug_info(&mut self, debuginfo: &VarDebugInfo<'tcx>) {
|
||||
if let Some(box VarDebugInfoFragment { ty, ref projection }) = debuginfo.composite {
|
||||
if let Some(VarDebugInfoFragment { ty, ref projection }) = debuginfo.composite {
|
||||
if ty.is_union() || ty.is_enum() {
|
||||
self.fail(
|
||||
START_BLOCK.start_location(),
|
||||
@@ -966,7 +966,7 @@ fn visit_place(&mut self, place: &Place<'tcx>, cntxt: PlaceContext, location: Lo
|
||||
}
|
||||
}
|
||||
|
||||
if let ClearCrossCrate::Set(box LocalInfo::DerefTemp) =
|
||||
if let ClearCrossCrate::Set(LocalInfo::DerefTemp) =
|
||||
self.body.local_decls[place.local].local_info
|
||||
&& !place.is_indirect_first_projection()
|
||||
{
|
||||
@@ -1457,7 +1457,7 @@ macro_rules! check_kinds {
|
||||
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (dest, rvalue)) => {
|
||||
StatementKind::Assign((dest, rvalue)) => {
|
||||
// LHS and RHS of the assignment must have the same type.
|
||||
let left_ty = dest.ty(&self.body.local_decls, self.tcx).ty;
|
||||
let right_ty = rvalue.ty(&self.body.local_decls, self.tcx);
|
||||
@@ -1475,7 +1475,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
}
|
||||
|
||||
if let Some(local) = dest.as_local()
|
||||
&& let ClearCrossCrate::Set(box LocalInfo::DerefTemp) =
|
||||
&& let ClearCrossCrate::Set(LocalInfo::DerefTemp) =
|
||||
self.body.local_decls[local].local_info
|
||||
&& !matches!(rvalue, Rvalue::CopyForDeref(_))
|
||||
{
|
||||
@@ -1498,7 +1498,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
);
|
||||
}
|
||||
}
|
||||
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => {
|
||||
StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(op)) => {
|
||||
let ty = op.ty(&self.body.local_decls, self.tcx);
|
||||
if !ty.is_bool() {
|
||||
self.fail(
|
||||
@@ -1507,7 +1507,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
);
|
||||
}
|
||||
}
|
||||
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
|
||||
StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping(
|
||||
CopyNonOverlapping { src, dst, count },
|
||||
)) => {
|
||||
let src_ty = src.ty(&self.body.local_decls, self.tcx);
|
||||
@@ -1642,7 +1642,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
|
||||
}
|
||||
|
||||
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
|
||||
if let ClearCrossCrate::Set(box LocalInfo::DerefTemp) = local_decl.local_info {
|
||||
if let ClearCrossCrate::Set(LocalInfo::DerefTemp) = local_decl.local_info {
|
||||
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
|
||||
self.fail(
|
||||
START_BLOCK.start_location(),
|
||||
|
||||
Reference in New Issue
Block a user