diff options
| author | Ralf Jung <post@ralfj.de> | 2018-11-06 11:04:10 +0100 | 
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2018-11-07 16:54:31 +0100 | 
| commit | f27cd60ae1819b3b23fc8c3cb21d5f7d457014a1 (patch) | |
| tree | f548de29565ba1739536057f2e2f362e79f71eef | |
| parent | 8315b11b6352cbd91ee096571c31ae7d3ac9613d (diff) | |
| download | rust-f27cd60ae1819b3b23fc8c3cb21d5f7d457014a1.tar.gz rust-f27cd60ae1819b3b23fc8c3cb21d5f7d457014a1.zip  | |
no more action on ref or cast, but add new MIR statement for escaping a ptr to raw
23 files changed, 159 insertions, 110 deletions
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index a73fe2b8a1a..1bd02dfeaca 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -257,6 +257,9 @@ for mir::StatementKind<'gcx> { mir::StatementKind::EndRegion(ref region_scope) => { region_scope.hash_stable(hcx, hasher); } + mir::StatementKind::EscapeToRaw(ref place) => { + place.hash_stable(hcx, hasher); + } mir::StatementKind::Retag { fn_entry, ref place } => { fn_entry.hash_stable(hcx, hasher); place.hash_stable(hcx, hasher); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 36bc2edcf58..0817c2e8bf2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1766,6 +1766,13 @@ pub enum StatementKind<'tcx> { place: Place<'tcx>, }, + /// Escape the given reference to a raw pointer, so that it can be accessed + /// without precise provenance tracking. These statements are currently only interpreted + /// by miri and only generated when "-Z mir-emit-retag" is passed. + /// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/> + /// for more details. + EscapeToRaw(Operand<'tcx>), + /// Mark one terminating point of a region scope (i.e. static region). /// (The starting point(s) arise implicitly from borrows.) EndRegion(region::Scope), @@ -1827,6 +1834,7 @@ impl<'tcx> Debug for Statement<'tcx> { EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)), Retag { fn_entry, ref place } => write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place), + EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place), StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place), StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place), SetDiscriminant { @@ -2968,6 +2976,7 @@ EnumTypeFoldableImpl! { (StatementKind::StorageDead)(a), (StatementKind::InlineAsm) { asm, outputs, inputs }, (StatementKind::Retag) { fn_entry, place }, + (StatementKind::EscapeToRaw)(place), (StatementKind::EndRegion)(a), (StatementKind::AscribeUserType)(a, v, b), (StatementKind::Nop), diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index c130e047e47..2a994ee0509 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -385,6 +385,9 @@ macro_rules! make_mir_visitor { location ); } + StatementKind::EscapeToRaw(ref $($mutability)* op) => { + self.visit_operand(op, location); + } StatementKind::StorageLive(ref $($mutability)* local) => { self.visit_local( local, @@ -1022,7 +1025,7 @@ pub enum MutatingUseContext<'tcx> { /// f(&mut x.y); /// Projection, - /// Retagging (updating the "Stacked Borrows" tag) + /// Retagging, a "Stacked Borrows" shadow state operation Retag, } diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs index c8c8e02bf05..8bda2c98594 100644 --- a/src/librustc_codegen_llvm/mir/statement.rs +++ b/src/librustc_codegen_llvm/mir/statement.rs @@ -105,8 +105,9 @@ impl FunctionCx<'a, 'll, 'tcx> { bx } mir::StatementKind::FakeRead(..) | - mir::StatementKind::EndRegion(_) | + mir::StatementKind::EndRegion(..) | mir::StatementKind::Retag { .. } | + mir::StatementKind::EscapeToRaw { .. } | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Nop => bx, } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index d4f00ab3bb9..533b777d67d 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -601,6 +601,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx StatementKind::Nop | StatementKind::AscribeUserType(..) | StatementKind::Retag { .. } + | StatementKind::EscapeToRaw { .. } | StatementKind::StorageLive(..) => { // `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant // to borrow check. diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index cfe03c2d1c7..576509c0fdd 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -137,6 +137,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> { StatementKind::Nop | StatementKind::AscribeUserType(..) | StatementKind::Retag { .. } | + StatementKind::EscapeToRaw { .. } | StatementKind::StorageLive(..) => { // `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant // to borrow check. diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 734ddbc3ab9..3c2301ba4a7 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1290,11 +1290,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } StatementKind::FakeRead(..) - | StatementKind::StorageLive(_) - | StatementKind::StorageDead(_) + | StatementKind::StorageLive(..) + | StatementKind::StorageDead(..) | StatementKind::InlineAsm { .. } | StatementKind::EndRegion(_) | StatementKind::Retag { .. } + | StatementKind::EscapeToRaw { .. } | StatementKind::Nop => {} } } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 69d2a89b5f2..811da9e1acc 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -339,6 +339,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { mir::StatementKind::SetDiscriminant { .. } | mir::StatementKind::StorageLive(..) | mir::StatementKind::Retag { .. } | + mir::StatementKind::EscapeToRaw { .. } | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Nop => {} diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 874e862de23..e6e165ef3de 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -301,8 +301,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { span_bug!(stmt.source_info.span, "SetDiscriminant should not exist during borrowck"); } - StatementKind::EndRegion(_) | + StatementKind::EndRegion(..) | StatementKind::Retag { .. } | + StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | StatementKind::Nop => {} } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 06748d60e45..118539fc58e 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -44,28 +44,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } Misc => { - let src_layout = src.layout; let src = self.read_immediate(src)?; - let src = if M::ENABLE_PTR_TRACKING_HOOKS && src_layout.ty.is_region_ptr() { - // The only `Misc` casts on references are those creating raw pointers. - assert!(dest.layout.ty.is_unsafe_ptr()); - // For the purpose of the "ptr tag hooks", treat this as creating - // a new, raw reference. - let place = self.ref_to_mplace(src)?; - self.create_ref(place, None)? - } else { - *src - }; - - if self.type_is_fat_ptr(src_layout.ty) { - match (src, self.type_is_fat_ptr(dest.layout.ty)) { + if self.type_is_fat_ptr(src.layout.ty) { + match (*src, self.type_is_fat_ptr(dest.layout.ty)) { // pointers to extern types (Immediate::Scalar(_),_) | // slices and trait objects to other slices/trait objects (Immediate::ScalarPair(..), true) => { // No change to immediate - self.write_immediate(src, dest)?; + self.write_immediate(*src, dest)?; } // slices and trait objects to thin pointers (dropping the metadata) (Immediate::ScalarPair(data, _), false) => { @@ -73,11 +61,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } } } else { - match src_layout.variants { + match src.layout.variants { layout::Variants::Single { index } => { - if let Some(def) = src_layout.ty.ty_adt_def() { + if let Some(def) = src.layout.ty.ty_adt_def() { // Cast from a univariant enum - assert!(src_layout.is_zst()); + assert!(src.layout.is_zst()); let discr_val = def .discriminant_for_variant(*self.tcx, index) .val; @@ -90,8 +78,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> layout::Variants::NicheFilling { .. } => {}, } - let src = src.to_scalar()?; - let dest_val = self.cast_scalar(src, src_layout, dest.layout)?; + let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?; self.write_scalar(dest_val, dest)?; } } diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 27cf28ef41e..214ffd071cc 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -211,18 +211,6 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { kind: MemoryKind<Self::MemoryKinds>, ) -> EvalResult<'tcx, Pointer<Self::PointerTag>>; - /// Executed when evaluating the `&` operator: Creating a new reference. - /// This has the chance to adjust the tag. It should not change anything else! - /// `mutability` can be `None` in case a raw ptr is being created. - #[inline] - fn tag_reference( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - place: MPlaceTy<'tcx, Self::PointerTag>, - _mutability: Option<hir::Mutability>, - ) -> EvalResult<'tcx, Scalar<Self::PointerTag>> { - Ok(place.ptr) - } - /// Executed when evaluating the `*` operator: Following a reference. /// This has the chance to adjust the tag. It should not change anything else! /// `mutability` can be `None` in case a raw ptr is being dereferenced. @@ -235,7 +223,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { Ok(place.ptr) } - /// Execute a validation operation + /// Execute a retagging operation #[inline] fn retag( _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, @@ -244,4 +232,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { ) -> EvalResult<'tcx> { Ok(()) } + + /// Execute an escape-to-raw operation + #[inline] + fn escape_to_raw( + _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + _ptr: OpTy<'tcx, Self::PointerTag>, + ) -> EvalResult<'tcx> { + Ok(()) + } } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 19430c85cf7..da62594cb22 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -151,6 +151,16 @@ impl<Tag> MemPlace<Tag> { // it now must be aligned. self.to_scalar_ptr_align().0.to_ptr() } + + /// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space. + /// This is the inverse of `ref_to_mplace`. + #[inline(always)] + pub fn to_ref(self) -> Immediate<Tag> { + match self.meta { + None => Immediate::Scalar(self.ptr.into()), + Some(meta) => Immediate::ScalarPair(self.ptr.into(), meta.into()), + } + } } impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { @@ -266,7 +276,7 @@ where M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<Tag, M::AllocExtra>)>, { /// Take a value, which represents a (thin or fat) reference, and make it a place. - /// Alignment is just based on the type. This is the inverse of `create_ref`. + /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. pub fn ref_to_mplace( &self, val: ImmTy<'tcx, M::PointerTag>, @@ -294,24 +304,6 @@ where Ok(mplace) } - /// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space. - /// This is the inverse of `ref_to_mplace`. - /// `mutbl` indicates whether we are create a shared or mutable ref, or a raw pointer (`None`). - pub fn create_ref( - &mut self, - mut place: MPlaceTy<'tcx, M::PointerTag>, - mutbl: Option<hir::Mutability>, - ) -> EvalResult<'tcx, Immediate<M::PointerTag>> { - // Pointer tag tracking might want to adjust the tag - if M::ENABLE_PTR_TRACKING_HOOKS { - place.mplace.ptr = M::tag_reference(self, place, mutbl)? - } - Ok(match place.meta { - None => Immediate::Scalar(place.ptr.into()), - Some(meta) => Immediate::ScalarPair(place.ptr.into(), meta.into()), - }) - } - /// Offset a pointer to project to a field. Unlike place_field, this is always /// possible without allocating, so it can take &self. Also return the field's layout. /// This supports both struct and array fields. diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index db055204c0a..ac13e5982da 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -12,7 +12,7 @@ //! //! The main entry point is the `step` method. -use rustc::{hir, mir}; +use rustc::mir; use rustc::ty::layout::LayoutOf; use rustc::mir::interpret::{EvalResult, Scalar, PointerArithmetic}; @@ -118,12 +118,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // interpreter is solely intended for borrowck'ed code. FakeRead(..) => {} - // Retagging. + // Stacked Borrows. Retag { fn_entry, ref place } => { let dest = self.eval_place(place)?; M::retag(self, fn_entry, dest)?; } + EscapeToRaw(ref op) => { + let op = self.eval_operand(op, None)?; + M::escape_to_raw(self, op)?; + } + // Statements we do not track. EndRegion(..) => {} AscribeUserType(..) => {} @@ -247,19 +252,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> )?; } - Ref(_, borrow_kind, ref place) => { + Ref(_, _, ref place) => { let src = self.eval_place(place)?; let val = self.force_allocation(src)?; - let mutbl = match borrow_kind { - mir::BorrowKind::Mut { .. } | - mir::BorrowKind::Unique => - hir::MutMutable, - mir::BorrowKind::Shared | - mir::BorrowKind::Shallow => - hir::MutImmutable, - }; - let val = self.create_ref(val, Some(mutbl))?; - self.write_immediate(val, dest)?; + self.write_immediate(val.to_ref(), dest)?; } NullaryOp(mir::NullOp::Box, _) => { diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index b5df625b302..4cd7ca8182e 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -447,10 +447,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> }; let arg = OpTy { - op: Operand::Immediate(self.create_ref( - place, - None // this is a "raw reference" - )?), + op: Operand::Immediate(place.to_ref()), layout: self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?, }; diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index a50011cf5a1..0be91c3c339 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -20,20 +20,22 @@ use transform::{MirPass, MirSource}; pub struct AddRetag; -/// Determines whether this place is local: If it is part of a local variable. -/// We do not consider writes to pointers local, only writes that immediately assign -/// to a local variable. -/// One important property here is that evaluating the place immediately after -/// the assignment must produce the same place as what was used during the assignment. -fn is_local<'tcx>( +/// Determines whether this place is "stable": Whether, if we evaluate it again +/// after the assignment, we can be sure to obtain the same place value. +/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic +/// copies. Data races are UB.) +fn is_stable<'tcx>( place: &Place<'tcx>, ) -> bool { use rustc::mir::Place::*; match *place { - Local { .. } => true, - Promoted(_) | - Static(_) => false, + // Locals and statics have stable addresses, for sure + Local { .. } | + Promoted { .. } | + Static { .. } => + true, + // Recurse for projections Projection(ref proj) => { match proj.elem { ProjectionElem::Deref | @@ -47,15 +49,15 @@ fn is_local<'tcx>( ProjectionElem::Subslice { .. } | ProjectionElem::Downcast { .. } => // These just offset by a constant, entirely independent of everything else. - is_local(&proj.base), + is_stable(&proj.base), } } } } -/// Determine whether this type has a reference in it, recursing below compound types but +/// Determine whether this type may have a reference in it, recursing below compound types but /// not below references. -fn has_reference<'a, 'gcx, 'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { +fn may_have_reference<'a, 'gcx, 'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { match ty.sty { // Primitive types that are not references ty::Bool | ty::Char | @@ -68,12 +70,12 @@ fn has_reference<'a, 'gcx, 'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> b ty::Adt(..) if ty.is_box() => true, // Compound types ty::Array(ty, ..) | ty::Slice(ty) => - has_reference(ty, tcx), + may_have_reference(ty, tcx), ty::Tuple(tys) => - tys.iter().any(|ty| has_reference(ty, tcx)), + tys.iter().any(|ty| may_have_reference(ty, tcx)), ty::Adt(adt, substs) => adt.variants.iter().any(|v| v.fields.iter().any(|f| - has_reference(f.ty(tcx, substs), tcx) + may_have_reference(f.ty(tcx, substs), tcx) )), // Conservative fallback _ => true, @@ -92,7 +94,9 @@ impl MirPass for AddRetag { let (span, arg_count) = (mir.span, mir.arg_count); let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut(); let needs_retag = |place: &Place<'tcx>| { - is_local(place) && has_reference(place.ty(&*local_decls, tcx).to_ty(tcx), tcx) + // FIXME: Instead of giving up for unstable places, we should introduce + // a temporary and retag on that. + is_stable(place) && may_have_reference(place.ty(&*local_decls, tcx).to_ty(tcx), tcx) }; // PART 1 @@ -118,23 +122,29 @@ impl MirPass for AddRetag { } // PART 2 - // Retag return values of functions. + // Retag return values of functions. Also escape-to-raw the argument of `drop`. // We collect the return destinations because we cannot mutate while iterating. let mut returns: Vec<(SourceInfo, Place<'tcx>, BasicBlock)> = Vec::new(); for block_data in basic_blocks.iter_mut() { - match block_data.terminator { - Some(Terminator { kind: TerminatorKind::Call { ref destination, .. }, - source_info }) => { + match block_data.terminator().kind { + TerminatorKind::Call { ref destination, .. } => { // Remember the return destination for later if let Some(ref destination) = destination { if needs_retag(&destination.0) { - returns.push((source_info, destination.0.clone(), destination.1)); + returns.push(( + block_data.terminator().source_info, + destination.0.clone(), + destination.1, + )); } } } + TerminatorKind::Drop { .. } | + TerminatorKind::DropAndReplace { .. } => { + // `Drop` is also a call, but it doesn't return anything so we are good. + } _ => { // Not a block ending in a Call -> ignore. - // `Drop` is also a call, but it doesn't return anything so we are good. } } } @@ -153,21 +163,43 @@ impl MirPass for AddRetag { // iterate backwards using indices. for i in (0..block_data.statements.len()).rev() { match block_data.statements[i].kind { - // Assignments can make values obtained elsewhere "local". - // We could try to be smart here and e.g. only retag if the assignment - // loaded from memory, but that seems risky: We might miss a subtle corner - // case. - StatementKind::Assign(ref place, box Rvalue::Use(..)) - if needs_retag(place) => { + // If we are casting *from* a reference, we may have to escape-to-raw. + StatementKind::Assign(_, box Rvalue::Cast( + CastKind::Misc, + ref src, + dest_ty, + )) => { + let src_ty = src.ty(&*local_decls, tcx); + if src_ty.is_region_ptr() { + // The only `Misc` casts on references are those creating raw pointers. + assert!(dest_ty.is_unsafe_ptr()); + // Insert escape-to-raw before the cast. We are not concerned + // with stability here: Our EscapeToRaw will not change the value + // that the cast will then use. + // `src` might be a "move", but we rely on this not actually moving + // but just doing a memcpy. It is crucial that we do EscapeToRaw + // on the src because we need it with its original type. + let source_info = block_data.statements[i].source_info; + block_data.statements.insert(i, Statement { + source_info, + kind: StatementKind::EscapeToRaw(src.clone()), + }); + } + } + // Assignments of reference or ptr type are the ones where we may have + // to update tags. This includes `x = &[mut] ...` and hence + // we also retag after taking a reference! + StatementKind::Assign(ref place, _) if needs_retag(place) => { // Insert a retag after the assignment. let source_info = block_data.statements[i].source_info; - block_data.statements.insert(i+1,Statement { + block_data.statements.insert(i+1, Statement { source_info, kind: StatementKind::Retag { fn_entry: false, place: place.clone() }, }); } + // Do nothing for the rest _ => {}, - } + }; } } } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index c28bb0ca357..4ebeebca227 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -114,6 +114,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { StatementKind::StorageDead(..) | StatementKind::EndRegion(..) | StatementKind::Retag { .. } | + StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | StatementKind::Nop => { // safe (at least as emitted during MIR construction) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index ca9c4eb9b8b..5fd83321296 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1168,6 +1168,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { StatementKind::InlineAsm {..} | StatementKind::EndRegion(_) | StatementKind::Retag { .. } | + StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | StatementKind::Nop => {} } diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 1e193485950..ed13063cfdf 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -242,6 +242,7 @@ fn check_statement( | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Retag { .. } + | StatementKind::EscapeToRaw { .. } | StatementKind::EndRegion(_) | StatementKind::AscribeUserType(..) | StatementKind::Nop => Ok(()), diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index c1c127fa8d6..445ffbbcf34 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -65,10 +65,11 @@ impl RemoveNoopLandingPads { // turn a landing pad to a non-nop } - StatementKind::Assign(_, _) | + StatementKind::Assign { .. } | StatementKind::SetDiscriminant { .. } | StatementKind::InlineAsm { .. } | - StatementKind::Retag { .. } => { + StatementKind::Retag { .. } | + StatementKind::EscapeToRaw { .. } => { return false; } } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index a5a19f04b7e..8f026c706fd 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -163,6 +163,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir::StatementKind::InlineAsm { .. } | mir::StatementKind::EndRegion(_) | mir::StatementKind::Retag { .. } | + mir::StatementKind::EscapeToRaw { .. } | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Nop => continue, mir::StatementKind::SetDiscriminant{ .. } => diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index ecfe7d13782..68840ed4a48 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -85,6 +85,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { StatementKind::FakeRead(..) => "StatementKind::FakeRead", StatementKind::EndRegion(..) => "StatementKind::EndRegion", StatementKind::Retag { .. } => "StatementKind::Retag", + StatementKind::EscapeToRaw { .. } => "StatementKind::EscapeToRaw", StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", StatementKind::StorageLive(..) => "StatementKind::StorageLive", StatementKind::StorageDead(..) => "StatementKind::StorageDead", diff --git a/src/test/mir-opt/inline-retag.rs b/src/test/mir-opt/inline-retag.rs index 4b3280ee561..1e5e1ad5ed1 100644 --- a/src/test/mir-opt/inline-retag.rs +++ b/src/test/mir-opt/inline-retag.rs @@ -32,6 +32,8 @@ fn bar() -> bool { // bb0: { // ... // Retag(_3); +// ... +// Retag(_3); // Retag(_6); // StorageLive(_9); // _9 = (*_3); diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 9c013008ab2..7da55c0868c 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -26,7 +26,9 @@ fn main() { { let v = Test(0).foo(&mut x); // just making sure we do not panic when there is a tuple struct ctor let w = { v }; // assignment - let _w = w; // reborrow + let w = w; // reborrow + // escape-to-raw (mut) + let _w = w as *mut _; } // Also test closures @@ -35,6 +37,9 @@ fn main() { // need to call `foo_shr` or it doesn't even get generated Test(0).foo_shr(&0); + + // escape-to-raw (shr) + let _w = _w as *const _; } // END RUST SOURCE @@ -44,6 +49,7 @@ fn main() { // Retag([fn entry] _2); // ... // _0 = &mut (*_3); +// Retag(_0); // ... // return; // } @@ -73,23 +79,36 @@ fn main() { // _9 = move _3; // Retag(_9); // _8 = &mut (*_9); +// Retag(_8); // StorageDead(_9); // StorageLive(_10); // _10 = move _8; // Retag(_10); // ... -// _13 = move _14(move _15) -> bb2; +// _14 = &mut (*_10); +// Retag(_14); +// EscapeToRaw(move _14); +// _13 = move _14 as *mut i32 (Misc); +// ... +// _17 = move _18(move _19) -> bb2; // } // // bb2: { -// Retag(_13); +// Retag(_17); +// ... +// _21 = const Test::foo_shr(move _22, move _24) -> bb3; +// } +// +// bb3: { // ... +// return; // } +// // ... // } // END rustc.main.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}(_1: &[closure@NodeId(117)], _2: &i32) -> &i32 { +// fn main::{{closure}}(_1: &[closure@NodeId(124)], _2: &i32) -> &i32 { // ... // bb0: { // Retag([fn entry] _1);  | 
