Skip to content

Commit 66910ba

Browse files
committed
Auto merge of #55125 - RalfJung:stacked-borrows, r=oli-obk
miri engine: Hooks for basic stacked borrows r? @oli-obk
2 parents 554b787 + 3f5b550 commit 66910ba

File tree

14 files changed

+312
-148
lines changed

14 files changed

+312
-148
lines changed

src/librustc/mir/interpret/mod.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ impl<'tcx, M: fmt::Debug + Eq + Hash + Clone> AllocMap<'tcx, M> {
524524
}
525525

526526
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
527-
pub struct Allocation<Tag=()> {
527+
pub struct Allocation<Tag=(),Extra=()> {
528528
/// The actual bytes of the allocation.
529529
/// Note that the bytes of a pointer represent the offset of the pointer
530530
pub bytes: Vec<u8>,
@@ -541,9 +541,11 @@ pub struct Allocation<Tag=()> {
541541
/// Also used by codegen to determine if a static should be put into mutable memory,
542542
/// which happens for `static mut` and `static` with interior mutability.
543543
pub mutability: Mutability,
544+
/// Extra state for the machine.
545+
pub extra: Extra,
544546
}
545547

546-
impl<Tag> Allocation<Tag> {
548+
impl<Tag, Extra: Default> Allocation<Tag, Extra> {
547549
/// Creates a read-only allocation initialized by the given bytes
548550
pub fn from_bytes(slice: &[u8], align: Align) -> Self {
549551
let mut undef_mask = UndefMask::new(Size::ZERO);
@@ -554,6 +556,7 @@ impl<Tag> Allocation<Tag> {
554556
undef_mask,
555557
align,
556558
mutability: Mutability::Immutable,
559+
extra: Extra::default(),
557560
}
558561
}
559562

@@ -569,6 +572,7 @@ impl<Tag> Allocation<Tag> {
569572
undef_mask: UndefMask::new(size),
570573
align,
571574
mutability: Mutability::Mutable,
575+
extra: Extra::default(),
572576
}
573577
}
574578
}

src/librustc_mir/const_eval.rs

+39-13
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,19 @@ use std::collections::hash_map::Entry;
1919
use rustc::hir::{self, def_id::DefId};
2020
use rustc::mir::interpret::ConstEvalErr;
2121
use rustc::mir;
22-
use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
23-
use rustc::ty::layout::{self, LayoutOf, TyLayout};
22+
use rustc::ty::{self, Ty, TyCtxt, Instance, query::TyCtxtAt};
23+
use rustc::ty::layout::{self, Size, LayoutOf, TyLayout};
2424
use rustc::ty::subst::Subst;
2525
use rustc_data_structures::indexed_vec::IndexVec;
2626
use rustc_data_structures::fx::FxHashMap;
2727

2828
use syntax::ast::Mutability;
2929
use syntax::source_map::{Span, DUMMY_SP};
3030

31-
use rustc::mir::interpret::{
32-
EvalResult, EvalError, EvalErrorKind, GlobalId,
33-
Scalar, Allocation, AllocId, ConstValue,
34-
};
3531
use interpret::{self,
36-
PlaceTy, MemPlace, OpTy, Operand, Value,
37-
EvalContext, StackPopCleanup, MemoryKind,
32+
PlaceTy, MemPlace, OpTy, Operand, Value, Pointer, Scalar, ConstValue,
33+
EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup,
34+
Allocation, AllocId, MemoryKind,
3835
snapshot,
3936
};
4037

@@ -53,7 +50,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
5350
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
5451
debug!("mk_borrowck_eval_cx: {:?}", instance);
5552
let param_env = tcx.param_env(instance.def_id());
56-
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), ());
53+
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
5754
// insert a stack frame so any queries have the correct substs
5855
// cannot use `push_stack_frame`; if we do `const_prop` explodes
5956
ecx.stack.push(interpret::Frame {
@@ -76,7 +73,7 @@ pub fn mk_eval_cx<'a, 'tcx>(
7673
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'tcx, 'tcx>> {
7774
debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
7875
let span = tcx.def_span(instance.def_id());
79-
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), ());
76+
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
8077
let mir = ecx.load_mir(instance.def)?;
8178
// insert a stack frame so any queries have the correct substs
8279
ecx.push_stack_frame(
@@ -155,7 +152,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
155152
// and try improving it down the road when more information is available
156153
let span = tcx.def_span(cid.instance.def_id());
157154
let span = mir.map(|mir| mir.span).unwrap_or(span);
158-
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), ());
155+
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
159156
let r = eval_body_using_ecx(&mut ecx, cid, mir, param_env);
160157
(r, ecx)
161158
}
@@ -333,16 +330,25 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
333330
type CompileTimeEvalContext<'a, 'mir, 'tcx> =
334331
EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>;
335332

333+
impl interpret::MayLeak for ! {
334+
#[inline(always)]
335+
fn may_leak(self) -> bool {
336+
// `self` is uninhabited
337+
self
338+
}
339+
}
340+
336341
impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
337342
for CompileTimeInterpreter<'a, 'mir, 'tcx>
338343
{
339-
type MemoryData = ();
340344
type MemoryKinds = !;
345+
type AllocExtra = ();
341346
type PointerTag = ();
342347

343-
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation<()>)>;
348+
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
344349

345350
const STATIC_KIND: Option<!> = None; // no copying of statics allowed
351+
const ENABLE_PTR_TRACKING_HOOKS: bool = false; // we don't have no provenance
346352

347353
#[inline(always)]
348354
fn enforce_validity(_ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool {
@@ -456,6 +462,26 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
456462
&ecx.stack[..],
457463
)
458464
}
465+
466+
#[inline(always)]
467+
fn tag_reference(
468+
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
469+
_ptr: Pointer<Self::PointerTag>,
470+
_pointee_ty: Ty<'tcx>,
471+
_pointee_size: Size,
472+
_borrow_kind: Option<mir::BorrowKind>,
473+
) -> EvalResult<'tcx, Self::PointerTag> {
474+
Ok(())
475+
}
476+
477+
#[inline(always)]
478+
fn tag_dereference(
479+
_ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
480+
_ptr: Pointer<Self::PointerTag>,
481+
_ptr_ty: Ty<'tcx>,
482+
) -> EvalResult<'tcx, Self::PointerTag> {
483+
Ok(())
484+
}
459485
}
460486

461487
/// Project to a field of a (variant of a) const

src/librustc_mir/interpret/cast.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,35 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
3737
kind: CastKind,
3838
dest: PlaceTy<'tcx, M::PointerTag>,
3939
) -> EvalResult<'tcx> {
40-
let src_layout = src.layout;
41-
let dst_layout = dest.layout;
4240
use rustc::mir::CastKind::*;
4341
match kind {
4442
Unsize => {
4543
self.unsize_into(src, dest)?;
4644
}
4745

4846
Misc => {
47+
let src_layout = src.layout;
4948
let src = self.read_value(src)?;
49+
50+
let src = if M::ENABLE_PTR_TRACKING_HOOKS && src_layout.ty.is_region_ptr() {
51+
// The only `Misc` casts on references are those creating raw pointers.
52+
assert!(dest.layout.ty.is_unsafe_ptr());
53+
// For the purpose of the "ptr tag hooks", treat this as creating
54+
// a new, raw reference.
55+
let place = self.ref_to_mplace(src)?;
56+
self.create_ref(place, None)?
57+
} else {
58+
*src
59+
};
60+
5061
if self.type_is_fat_ptr(src_layout.ty) {
51-
match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
62+
match (src, self.type_is_fat_ptr(dest.layout.ty)) {
5263
// pointers to extern types
5364
(Value::Scalar(_),_) |
5465
// slices and trait objects to other slices/trait objects
5566
(Value::ScalarPair(..), true) => {
5667
// No change to value
57-
self.write_value(*src, dest)?;
68+
self.write_value(src, dest)?;
5869
}
5970
// slices and trait objects to thin pointers (dropping the metadata)
6071
(Value::ScalarPair(data, _), false) => {
@@ -65,11 +76,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
6576
match src_layout.variants {
6677
layout::Variants::Single { index } => {
6778
if let Some(def) = src_layout.ty.ty_adt_def() {
79+
// Cast from a univariant enum
80+
assert!(src_layout.is_zst());
6881
let discr_val = def
6982
.discriminant_for_variant(*self.tcx, index)
7083
.val;
7184
return self.write_scalar(
72-
Scalar::from_uint(discr_val, dst_layout.size),
85+
Scalar::from_uint(discr_val, dest.layout.size),
7386
dest);
7487
}
7588
}
@@ -85,7 +98,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
8598

8699
ReifyFnPointer => {
87100
// The src operand does not matter, just its type
88-
match src_layout.ty.sty {
101+
match src.layout.ty.sty {
89102
ty::FnDef(def_id, substs) => {
90103
if self.tcx.has_attr(def_id, "rustc_args_required_const") {
91104
bug!("reifying a fn ptr that requires \
@@ -117,7 +130,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
117130

118131
ClosureFnPointer => {
119132
// The src operand does not matter, just its type
120-
match src_layout.ty.sty {
133+
match src.layout.ty.sty {
121134
ty::Closure(def_id, substs) => {
122135
let substs = self.tcx.subst_and_normalize_erasing_regions(
123136
self.substs(),

0 commit comments

Comments
 (0)