rustc_const_eval: remove ref patterns (+some pattern matching imps)

This commit is contained in:
Maybe Waffle 2022-12-23 15:15:21 +00:00
parent 85357e3e2e
commit 3dca58e249
14 changed files with 125 additions and 139 deletions

View File

@ -36,16 +36,16 @@ impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
impl fmt::Display for ConstEvalErrKind { impl fmt::Display for ConstEvalErrKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use self::ConstEvalErrKind::*; use self::ConstEvalErrKind::*;
match *self { match self {
ConstAccessesStatic => write!(f, "constant accesses static"), ConstAccessesStatic => write!(f, "constant accesses static"),
ModifiedGlobal => { ModifiedGlobal => {
write!(f, "modifying a static's initial value from another static's initializer") write!(f, "modifying a static's initial value from another static's initializer")
} }
AssertFailure(ref msg) => write!(f, "{:?}", msg), AssertFailure(msg) => write!(f, "{:?}", msg),
Panic { msg, line, col, file } => { Panic { msg, line, col, file } => {
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col) write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col)
} }
Abort(ref msg) => write!(f, "{}", msg), Abort(msg) => write!(f, "{}", msg),
} }
} }
} }

View File

@ -167,7 +167,7 @@ pub(super) fn op_to_const<'tcx>(
} }
}; };
match immediate { match immediate {
Left(ref mplace) => to_const_value(mplace), Left(mplace) => to_const_value(&mplace),
// see comment on `let try_as_immediate` above // see comment on `let try_as_immediate` above
Right(imm) => match *imm { Right(imm) => match *imm {
_ if imm.layout.is_zst() => ConstValue::ZeroSized, _ if imm.layout.is_zst() => ConstValue::ZeroSized,

View File

@ -533,7 +533,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
let eval_to_int = let eval_to_int =
|op| ecx.read_immediate(&ecx.eval_operand(op, None)?).map(|x| x.to_const_int()); |op| ecx.read_immediate(&ecx.eval_operand(op, None)?).map(|x| x.to_const_int());
let err = match msg { let err = match msg {
BoundsCheck { ref len, ref index } => { BoundsCheck { len, index } => {
let len = eval_to_int(len)?; let len = eval_to_int(len)?;
let index = eval_to_int(index)?; let index = eval_to_int(index)?;
BoundsCheck { len, index } BoundsCheck { len, index }

View File

@ -347,7 +347,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?; let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest) self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
} }
(_, &ty::Dynamic(ref data, _, ty::Dyn)) => { (_, &ty::Dynamic(data, _, ty::Dyn)) => {
// Initial cast from sized to dyn trait // Initial cast from sized to dyn trait
let vtable = self.get_vtable_ptr(src_pointee_ty, data.principal())?; let vtable = self.get_vtable_ptr(src_pointee_ty, data.principal())?;
let ptr = self.read_scalar(src)?; let ptr = self.read_scalar(src)?;

View File

@ -79,9 +79,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
} }
sym::variant_count => match tp_ty.kind() { sym::variant_count => match tp_ty.kind() {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
ty::Adt(ref adt, _) => { ty::Adt(adt, _) => ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx),
ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx)
}
ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => { ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
throw_inval!(TooGeneric) throw_inval!(TooGeneric)
} }

View File

@ -863,7 +863,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
write!(fmt, "{id:?}")?; write!(fmt, "{id:?}")?;
match self.ecx.memory.alloc_map.get(id) { match self.ecx.memory.alloc_map.get(id) {
Some(&(kind, ref alloc)) => { Some((kind, alloc)) => {
// normal alloc // normal alloc
write!(fmt, " ({}, ", kind)?; write!(fmt, " ({}, ", kind)?;
write_allocation_track_relocs( write_allocation_track_relocs(

View File

@ -363,11 +363,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
src: &OpTy<'tcx, M::Provenance>, src: &OpTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> { ) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> {
Ok(match src.as_mplace_or_imm() { Ok(match src.as_mplace_or_imm() {
Left(ref mplace) => { Left(mplace) => {
if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? { if let Some(val) = self.read_immediate_from_mplace_raw(&mplace)? {
Right(val) Right(val)
} else { } else {
Left(*mplace) Left(mplace)
} }
} }
Right(val) => Right(val), Right(val) => Right(val),
@ -533,11 +533,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
layout: Option<TyAndLayout<'tcx>>, layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
use rustc_middle::mir::Operand::*; use rustc_middle::mir::Operand::*;
let op = match *mir_op { let op = match mir_op {
// FIXME: do some more logic on `move` to invalidate the old location // FIXME: do some more logic on `move` to invalidate the old location
Copy(place) | Move(place) => self.eval_place_to_op(place, layout)?, &(Copy(place) | Move(place)) => self.eval_place_to_op(place, layout)?,
Constant(ref constant) => { Constant(constant) => {
let c = let c =
self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?; self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?;

View File

@ -87,9 +87,9 @@ where
field: usize, field: usize,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
let base = match base.as_mplace_or_imm() { let base = match base.as_mplace_or_imm() {
Left(ref mplace) => { Left(mplace) => {
// We can reuse the mplace field computation logic for indirect operands. // We can reuse the mplace field computation logic for indirect operands.
let field = self.mplace_field(mplace, field)?; let field = self.mplace_field(&mplace, field)?;
return Ok(field.into()); return Ok(field.into());
} }
Right(value) => value, Right(value) => value,

View File

@ -111,7 +111,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
M::retag_place_contents(self, *kind, &dest)?; M::retag_place_contents(self, *kind, &dest)?;
} }
Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?, Intrinsic(box intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
// Statements we do not track. // Statements we do not track.
AscribeUserType(..) => {} AscribeUserType(..) => {}
@ -151,50 +151,50 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Also see https://github.com/rust-lang/rust/issues/68364. // Also see https://github.com/rust-lang/rust/issues/68364.
use rustc_middle::mir::Rvalue::*; use rustc_middle::mir::Rvalue::*;
match *rvalue { match rvalue {
ThreadLocalRef(did) => { ThreadLocalRef(did) => {
let ptr = M::thread_local_static_base_pointer(self, did)?; let ptr = M::thread_local_static_base_pointer(self, *did)?;
self.write_pointer(ptr, &dest)?; self.write_pointer(ptr, &dest)?;
} }
Use(ref operand) => { Use(operand) => {
// Avoid recomputing the layout // Avoid recomputing the layout
let op = self.eval_operand(operand, Some(dest.layout))?; let op = self.eval_operand(operand, Some(dest.layout))?;
self.copy_op(&op, &dest, /*allow_transmute*/ false)?; self.copy_op(&op, &dest, /*allow_transmute*/ false)?;
} }
CopyForDeref(ref place) => { CopyForDeref(place) => {
let op = self.eval_place_to_op(*place, Some(dest.layout))?; let op = self.eval_place_to_op(*place, Some(dest.layout))?;
self.copy_op(&op, &dest, /* allow_transmute*/ false)?; self.copy_op(&op, &dest, /* allow_transmute*/ false)?;
} }
BinaryOp(bin_op, box (ref left, ref right)) => { BinaryOp(bin_op, box (left, right)) => {
let layout = binop_left_homogeneous(bin_op).then_some(dest.layout); let layout = binop_left_homogeneous(*bin_op).then_some(dest.layout);
let left = self.read_immediate(&self.eval_operand(left, layout)?)?; let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
let layout = binop_right_homogeneous(bin_op).then_some(left.layout); let layout = binop_right_homogeneous(*bin_op).then_some(left.layout);
let right = self.read_immediate(&self.eval_operand(right, layout)?)?; let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
self.binop_ignore_overflow(bin_op, &left, &right, &dest)?; self.binop_ignore_overflow(*bin_op, &left, &right, &dest)?;
} }
CheckedBinaryOp(bin_op, box (ref left, ref right)) => { CheckedBinaryOp(bin_op, box (left, right)) => {
// Due to the extra boolean in the result, we can never reuse the `dest.layout`. // Due to the extra boolean in the result, we can never reuse the `dest.layout`.
let left = self.read_immediate(&self.eval_operand(left, None)?)?; let left = self.read_immediate(&self.eval_operand(left, None)?)?;
let layout = binop_right_homogeneous(bin_op).then_some(left.layout); let layout = binop_right_homogeneous(*bin_op).then_some(left.layout);
let right = self.read_immediate(&self.eval_operand(right, layout)?)?; let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
self.binop_with_overflow( self.binop_with_overflow(
bin_op, /*force_overflow_checks*/ false, &left, &right, &dest, *bin_op, /*force_overflow_checks*/ false, &left, &right, &dest,
)?; )?;
} }
UnaryOp(un_op, ref operand) => { UnaryOp(un_op, operand) => {
// The operand always has the same type as the result. // The operand always has the same type as the result.
let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?; let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?;
let val = self.unary_op(un_op, &val)?; let val = self.unary_op(*un_op, &val)?;
assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op); assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op);
self.write_immediate(*val, &dest)?; self.write_immediate(*val, &dest)?;
} }
Aggregate(box ref kind, ref operands) => { Aggregate(box kind, operands) => {
assert!(matches!(kind, mir::AggregateKind::Array(..))); assert!(matches!(kind, mir::AggregateKind::Array(..)));
for (field_index, operand) in operands.iter().enumerate() { for (field_index, operand) in operands.iter().enumerate() {
@ -204,7 +204,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
} }
Repeat(ref operand, _) => { Repeat(operand, _) => {
let src = self.eval_operand(operand, None)?; let src = self.eval_operand(operand, None)?;
assert!(src.layout.is_sized()); assert!(src.layout.is_sized());
let dest = self.force_allocation(&dest)?; let dest = self.force_allocation(&dest)?;
@ -241,14 +241,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
Len(place) => { Len(place) => {
let src = self.eval_place(place)?; let src = self.eval_place(*place)?;
let op = self.place_to_op(&src)?; let op = self.place_to_op(&src)?;
let len = op.len(self)?; let len = op.len(self)?;
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?; self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
} }
Ref(_, borrow_kind, place) => { Ref(_, borrow_kind, place) => {
let src = self.eval_place(place)?; let src = self.eval_place(*place)?;
let place = self.force_allocation(&src)?; let place = self.force_allocation(&src)?;
let val = ImmTy::from_immediate(place.to_ref(self), dest.layout); let val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
// A fresh reference was created, make sure it gets retagged. // A fresh reference was created, make sure it gets retagged.
@ -274,7 +274,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
false false
}; };
let src = self.eval_place(place)?; let src = self.eval_place(*place)?;
let place = self.force_allocation(&src)?; let place = self.force_allocation(&src)?;
let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout); let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
if !place_base_raw { if !place_base_raw {
@ -285,7 +285,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
NullaryOp(null_op, ty) => { NullaryOp(null_op, ty) => {
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?; let ty = self.subst_from_current_frame_and_normalize_erasing_regions(*ty)?;
let layout = self.layout_of(ty)?; let layout = self.layout_of(ty)?;
if layout.is_unsized() { if layout.is_unsized() {
// FIXME: This should be a span_bug (#80742) // FIXME: This should be a span_bug (#80742)
@ -302,21 +302,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?; self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
} }
ShallowInitBox(ref operand, _) => { ShallowInitBox(operand, _) => {
let src = self.eval_operand(operand, None)?; let src = self.eval_operand(operand, None)?;
let v = self.read_immediate(&src)?; let v = self.read_immediate(&src)?;
self.write_immediate(*v, &dest)?; self.write_immediate(*v, &dest)?;
} }
Cast(cast_kind, ref operand, cast_ty) => { Cast(cast_kind, operand, cast_ty) => {
let src = self.eval_operand(operand, None)?; let src = self.eval_operand(operand, None)?;
let cast_ty = let cast_ty =
self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty)?; self.subst_from_current_frame_and_normalize_erasing_regions(*cast_ty)?;
self.cast(&src, cast_kind, cast_ty, &dest)?; self.cast(&src, *cast_kind, cast_ty, &dest)?;
} }
Discriminant(place) => { Discriminant(place) => {
let op = self.eval_place_to_op(place, None)?; let op = self.eval_place_to_op(*place, None)?;
let discr_val = self.read_discriminant(&op)?.0; let discr_val = self.read_discriminant(&op)?.0;
self.write_scalar(discr_val, &dest)?; self.write_scalar(discr_val, &dest)?;
} }

View File

@ -22,14 +22,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
terminator: &mir::Terminator<'tcx>, terminator: &mir::Terminator<'tcx>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
use rustc_middle::mir::TerminatorKind::*; use rustc_middle::mir::TerminatorKind::*;
match terminator.kind { match &terminator.kind {
Return => { Return => {
self.pop_stack_frame(/* unwinding */ false)? self.pop_stack_frame(/* unwinding */ false)?
} }
Goto { target } => self.go_to_block(target), Goto { target } => self.go_to_block(*target),
SwitchInt { ref discr, ref targets } => { SwitchInt { discr, targets } => {
let discr = self.read_immediate(&self.eval_operand(discr, None)?)?; let discr = self.read_immediate(&self.eval_operand(discr, None)?)?;
trace!("SwitchInt({:?})", *discr); trace!("SwitchInt({:?})", *discr);
@ -55,15 +55,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.go_to_block(target_block); self.go_to_block(target_block);
} }
Call { Call { func, args, destination, target, cleanup, from_hir_call: _, fn_span: _ } => {
ref func,
ref args,
destination,
target,
ref cleanup,
from_hir_call: _,
fn_span: _,
} => {
let old_stack = self.frame_idx(); let old_stack = self.frame_idx();
let old_loc = self.frame().loc; let old_loc = self.frame().loc;
let func = self.eval_operand(func, None)?; let func = self.eval_operand(func, None)?;
@ -97,14 +89,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
), ),
}; };
let destination = self.eval_place(destination)?; let destination = self.eval_place(*destination)?;
self.eval_fn_call( self.eval_fn_call(
fn_val, fn_val,
(fn_sig.abi, fn_abi), (fn_sig.abi, fn_abi),
&args, &args,
with_caller_location, with_caller_location,
&destination, &destination,
target, *target,
match (cleanup, fn_abi.can_unwind) { match (cleanup, fn_abi.can_unwind) {
(Some(cleanup), true) => StackPopUnwind::Cleanup(*cleanup), (Some(cleanup), true) => StackPopUnwind::Cleanup(*cleanup),
(None, true) => StackPopUnwind::Skip, (None, true) => StackPopUnwind::Skip,
@ -118,7 +110,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
} }
Drop { place, target, unwind } => { &Drop { place, target, unwind } => {
let frame = self.frame(); let frame = self.frame();
let ty = place.ty(&frame.body.local_decls, *self.tcx).ty; let ty = place.ty(&frame.body.local_decls, *self.tcx).ty;
let ty = self.subst_from_frame_and_normalize_erasing_regions(frame, ty)?; let ty = self.subst_from_frame_and_normalize_erasing_regions(frame, ty)?;
@ -136,12 +128,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.drop_in_place(&place, instance, target, unwind)?; self.drop_in_place(&place, instance, target, unwind)?;
} }
Assert { ref cond, expected, ref msg, target, cleanup } => { Assert { cond, expected, msg, target, cleanup } => {
let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?; let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?;
if expected == cond_val { if *expected == cond_val {
self.go_to_block(target); self.go_to_block(*target);
} else { } else {
M::assert_panic(self, msg, cleanup)?; M::assert_panic(self, msg, *cleanup)?;
} }
} }
@ -174,8 +166,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
terminator.kind terminator.kind
), ),
InlineAsm { template, ref operands, options, destination, .. } => { InlineAsm { template, operands, options, destination, .. } => {
M::eval_inline_asm(self, template, operands, options)?; M::eval_inline_asm(self, template, operands, *options)?;
if options.contains(InlineAsmOptions::NORETURN) { if options.contains(InlineAsmOptions::NORETURN) {
throw_ub_format!("returned from noreturn inline assembly"); throw_ub_format!("returned from noreturn inline assembly");
} }

View File

@ -419,7 +419,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
) )
} }
// Recursive checking // Recursive checking
if let Some(ref mut ref_tracking) = self.ref_tracking { if let Some(ref_tracking) = self.ref_tracking.as_deref_mut() {
// Proceed recursively even for ZST, no reason to skip them! // Proceed recursively even for ZST, no reason to skip them!
// `!` is a ZST and we want to validate it. // `!` is a ZST and we want to validate it.
if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr) { if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr) {

View File

@ -481,12 +481,12 @@ macro_rules! make_value_visitor {
}; };
// Visit the fields of this value. // Visit the fields of this value.
match v.layout().fields { match &v.layout().fields {
FieldsShape::Primitive => {} FieldsShape::Primitive => {}
FieldsShape::Union(fields) => { FieldsShape::Union(fields) => {
self.visit_union(v, fields)?; self.visit_union(v, *fields)?;
} }
FieldsShape::Arbitrary { ref offsets, .. } => { FieldsShape::Arbitrary { offsets, .. } => {
// FIXME: We collect in a vec because otherwise there are lifetime // FIXME: We collect in a vec because otherwise there are lifetime
// errors: Projecting to a field needs access to `ecx`. // errors: Projecting to a field needs access to `ecx`.
let fields: Vec<InterpResult<'tcx, Self::V>> = let fields: Vec<InterpResult<'tcx, Self::V>> =

View File

@ -442,7 +442,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
self.super_rvalue(rvalue, location); self.super_rvalue(rvalue, location);
match *rvalue { match rvalue {
Rvalue::ThreadLocalRef(_) => self.check_op(ops::ThreadLocalAccess), Rvalue::ThreadLocalRef(_) => self.check_op(ops::ThreadLocalAccess),
Rvalue::Use(_) Rvalue::Use(_)
@ -451,18 +451,15 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
| Rvalue::Discriminant(..) | Rvalue::Discriminant(..)
| Rvalue::Len(_) => {} | Rvalue::Len(_) => {}
Rvalue::Aggregate(ref kind, ..) => { Rvalue::Aggregate(kind, ..) => {
if let AggregateKind::Generator(def_id, ..) = kind.as_ref() { if let AggregateKind::Generator(def_id, ..) = kind.as_ref()
if let Some(generator_kind) = self.tcx.generator_kind(def_id.to_def_id()) { && let Some(generator_kind @ hir::GeneratorKind::Async(..)) = self.tcx.generator_kind(def_id.to_def_id())
if matches!(generator_kind, hir::GeneratorKind::Async(..)) { {
self.check_op(ops::Generator(generator_kind)); self.check_op(ops::Generator(generator_kind));
} }
} }
}
}
Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, ref place) Rvalue::Ref(_, kind @ (BorrowKind::Mut { .. } | BorrowKind::Unique), place) => {
| Rvalue::Ref(_, kind @ BorrowKind::Unique, ref place) => {
let ty = place.ty(self.body, self.tcx).ty; let ty = place.ty(self.body, self.tcx).ty;
let is_allowed = match ty.kind() { let is_allowed = match ty.kind() {
// Inside a `static mut`, `&mut [...]` is allowed. // Inside a `static mut`, `&mut [...]` is allowed.
@ -491,12 +488,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
} }
} }
Rvalue::AddressOf(Mutability::Mut, ref place) => { Rvalue::AddressOf(Mutability::Mut, place) => {
self.check_mut_borrow(place.local, hir::BorrowKind::Raw) self.check_mut_borrow(place.local, hir::BorrowKind::Raw)
} }
Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, ref place) Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, place)
| Rvalue::AddressOf(Mutability::Not, ref place) => { | Rvalue::AddressOf(Mutability::Not, place) => {
let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>( let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
&self.ccx, &self.ccx,
&mut |local| self.qualifs.has_mut_interior(self.ccx, local, location), &mut |local| self.qualifs.has_mut_interior(self.ccx, local, location),
@ -564,7 +561,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
Rvalue::ShallowInitBox(_, _) => {} Rvalue::ShallowInitBox(_, _) => {}
Rvalue::UnaryOp(_, ref operand) => { Rvalue::UnaryOp(_, operand) => {
let ty = operand.ty(self.body, self.tcx); let ty = operand.ty(self.body, self.tcx);
if is_int_bool_or_char(ty) { if is_int_bool_or_char(ty) {
// Int, bool, and char operations are fine. // Int, bool, and char operations are fine.
@ -575,8 +572,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
} }
} }
Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) Rvalue::BinaryOp(op, box (lhs, rhs))
| Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) => { | Rvalue::CheckedBinaryOp(op, box (lhs, rhs)) => {
let lhs_ty = lhs.ty(self.body, self.tcx); let lhs_ty = lhs.ty(self.body, self.tcx);
let rhs_ty = rhs.ty(self.body, self.tcx); let rhs_ty = rhs.ty(self.body, self.tcx);
@ -585,13 +582,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
} else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() { } else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() {
assert_eq!(lhs_ty, rhs_ty); assert_eq!(lhs_ty, rhs_ty);
assert!( assert!(
op == BinOp::Eq matches!(
|| op == BinOp::Ne op,
|| op == BinOp::Le BinOp::Eq
|| op == BinOp::Lt | BinOp::Ne
|| op == BinOp::Ge | BinOp::Le
|| op == BinOp::Gt | BinOp::Lt
|| op == BinOp::Offset | BinOp::Ge
| BinOp::Gt
| BinOp::Offset
)
); );
self.check_op(ops::RawPtrComparison); self.check_op(ops::RawPtrComparison);

View File

@ -133,7 +133,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
} }
_ => { /* mark as unpromotable below */ } _ => { /* mark as unpromotable below */ }
} }
} else if let TempState::Defined { ref mut uses, .. } = *temp { } else if let TempState::Defined { uses, .. } = temp {
// We always allow borrows, even mutable ones, as we need // We always allow borrows, even mutable ones, as we need
// to promote mutable borrows of some ZSTs e.g., `&mut []`. // to promote mutable borrows of some ZSTs e.g., `&mut []`.
let allowed_use = match context { let allowed_use = match context {
@ -748,7 +748,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
if loc.statement_index < num_stmts { if loc.statement_index < num_stmts {
let (mut rvalue, source_info) = { let (mut rvalue, source_info) = {
let statement = &mut self.source[loc.block].statements[loc.statement_index]; let statement = &mut self.source[loc.block].statements[loc.statement_index];
let StatementKind::Assign(box (_, ref mut rhs)) = statement.kind else { let StatementKind::Assign(box (_, rhs)) = &mut statement.kind else {
span_bug!( span_bug!(
statement.source_info.span, statement.source_info.span,
"{:?} is not an assignment", "{:?} is not an assignment",
@ -778,9 +778,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
self.source[loc.block].terminator().clone() self.source[loc.block].terminator().clone()
} else { } else {
let terminator = self.source[loc.block].terminator_mut(); let terminator = self.source[loc.block].terminator_mut();
let target = match terminator.kind { let target = match &terminator.kind {
TerminatorKind::Call { target: Some(target), .. } => target, TerminatorKind::Call { target: Some(target), .. } => *target,
ref kind => { kind => {
span_bug!(terminator.source_info.span, "{:?} not promotable", kind); span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
} }
}; };
@ -814,7 +814,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
..terminator ..terminator
}; };
} }
ref kind => { kind => {
span_bug!(terminator.source_info.span, "{:?} not promotable", kind); span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
} }
}; };
@ -847,11 +847,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
let local_decls = &mut self.source.local_decls; let local_decls = &mut self.source.local_decls;
let loc = candidate.location; let loc = candidate.location;
let statement = &mut blocks[loc.block].statements[loc.statement_index]; let statement = &mut blocks[loc.block].statements[loc.statement_index];
match statement.kind { let StatementKind::Assign(box (_, Rvalue::Ref(region, borrow_kind, place)))= &mut statement.kind else {
StatementKind::Assign(box ( bug!()
_, };
Rvalue::Ref(ref mut region, borrow_kind, ref mut place),
)) => {
// Use the underlying local for this (necessarily interior) borrow. // Use the underlying local for this (necessarily interior) borrow.
let ty = local_decls[place.local].ty; let ty = local_decls[place.local].ty;
let span = statement.source_info.span; let span = statement.source_info.span;
@ -886,15 +885,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
Rvalue::Ref( Rvalue::Ref(
tcx.lifetimes.re_erased, tcx.lifetimes.re_erased,
borrow_kind, *borrow_kind,
Place { Place {
local: mem::replace(&mut place.local, promoted_ref), local: mem::replace(&mut place.local, promoted_ref),
projection: List::empty(), projection: List::empty(),
}, },
) )
}
_ => bug!(),
}
}; };
assert_eq!(self.new_block(), START_BLOCK); assert_eq!(self.new_block(), START_BLOCK);