Skip to content

Commit

Permalink
Auto merge of rust-lang#2670 - RalfJung:retag, r=RalfJung
Browse files Browse the repository at this point in the history
recreated by hand
  • Loading branch information
RalfJung committed Nov 17, 2022
2 parents afab05b + f1a8701 commit 331b93a
Showing 1 changed file with 49 additions and 48 deletions.
97 changes: 49 additions & 48 deletions src/tools/miri/src/stacked_borrows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use rustc_middle::mir::RetagKind;
use rustc_middle::ty::{
self,
layout::{HasParamEnv, LayoutOf},
Ty,
};
use rustc_target::abi::Abi;
use rustc_target::abi::Size;
Expand Down Expand Up @@ -983,28 +982,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
return visitor.visit_value(place);

// Determine mutability and whether to add a protector.
// Cannot use `builtin_deref` because that reports *immutable* for `Box`,
// making it useless.
fn qualify(ty: Ty<'_>, kind: RetagKind) -> Option<(RefKind, bool)> {
match ty.kind() {
// References are simple.
ty::Ref(_, _, Mutability::Mut) =>
Some((
RefKind::Unique { two_phase: kind == RetagKind::TwoPhase },
kind == RetagKind::FnEntry,
)),
ty::Ref(_, _, Mutability::Not) =>
Some((RefKind::Shared, kind == RetagKind::FnEntry)),
// Raw pointers need to be enabled.
ty::RawPtr(tym) if kind == RetagKind::Raw =>
Some((RefKind::Raw { mutable: tym.mutbl == Mutability::Mut }, false)),
// Boxes are handled separately due to that allocator situation,
// see the visitor below.
_ => None,
}
}

// The actual visitor.
struct RetagVisitor<'ecx, 'mir, 'tcx> {
ecx: &'ecx mut MiriInterpCx<'mir, 'tcx>,
Expand Down Expand Up @@ -1057,34 +1034,58 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
return Ok(());
}

let recurse_for_fields = || {
match self.retag_fields {
RetagFields::No => false,
RetagFields::Yes => true,
RetagFields::OnlyScalar => {
// Matching `ArgAbi::new` at the time of writing, only fields of
// `Scalar` and `ScalarPair` ABI are considered.
matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
// Check the type of this value to see what to do with it (retag, or recurse).
match place.layout.ty.kind() {
ty::Ref(_, _, mutbl) => {
let ref_kind = match mutbl {
Mutability::Mut =>
RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase },
Mutability::Not => RefKind::Shared,
};
self.retag_place(
place,
ref_kind,
self.retag_cause,
/*protector*/ self.kind == RetagKind::FnEntry,
)?;
}
ty::RawPtr(tym) => {
// We definitely do *not* want to recurse into raw pointers -- wide raw
// pointers have fields, and for dyn Trait pointees those can have reference
// type!
if self.kind == RetagKind::Raw {
// Raw pointers need to be enabled.
self.retag_place(
place,
RefKind::Raw { mutable: tym.mutbl == Mutability::Mut },
self.retag_cause,
/*protector*/ false,
)?;
}
}
_ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => {
// Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
// (Yes this means we technically also recursively retag the allocator itself
// even if field retagging is not enabled. *shrug*)
self.walk_value(place)?;
}
_ => {
// Not a reference/pointer/box. Only recurse if configured appropriately.
let recurse = match self.retag_fields {
RetagFields::No => false,
RetagFields::Yes => true,
RetagFields::OnlyScalar => {
// Matching `ArgAbi::new` at the time of writing, only fields of
// `Scalar` and `ScalarPair` ABI are considered.
matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
}
};
if recurse {
self.walk_value(place)?;
}
}
};

if let Some((ref_kind, protector)) = qualify(place.layout.ty, self.kind) {
self.retag_place(place, ref_kind, self.retag_cause, protector)?;
} else if matches!(place.layout.ty.kind(), ty::RawPtr(..)) {
// Wide raw pointers *do* have fields and their types are strange.
// vtables have a type like `&[*const (); 3]` or so!
// Do *not* recurse into them.
// (No need to worry about wide references, those always "qualify". And Boxes
// are handles specially by the visitor anyway.)
} else if recurse_for_fields()
|| place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box())
{
// Recurse deeper. Need to always recurse for `Box` to even hit `visit_box`.
// (Yes this means we technically also recursively retag the allocator itself
// even if field retagging is not enabled. *shrug*)
self.walk_value(place)?;
}

Ok(())
}
}
Expand Down

0 comments on commit 331b93a

Please sign in to comment.