Skip to content

Commit bccadeb

Browse files
authored
Merge pull request #564 from solson/rustup
Support two-phase borrows, and other rustup
2 parents 676204b + 8d1e117 commit bccadeb

File tree

8 files changed

+102
-19
lines changed

8 files changed

+102
-19
lines changed

benches/helpers/miri_helper.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub fn run(filename: &str, bencher: &mut Bencher) {
4747
let (entry_node_id, _, _) = state.session.entry_fn.borrow().expect(
4848
"no main or start function found",
4949
);
50-
let entry_def_id = tcx.hir.local_def_id(entry_node_id);
50+
let entry_def_id = tcx.hir().local_def_id(entry_node_id);
5151

5252
bencher.borrow_mut().iter(|| {
5353
eval_main(tcx, entry_def_id, false);

rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nightly-2018-12-03
1+
nightly-2018-12-08

src/bin/miri-rustc-tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
9393
fn visit_item(&mut self, i: &'hir hir::Item) {
9494
if let hir::ItemKind::Fn(.., body_id) = i.node {
9595
if i.attrs.iter().any(|attr| attr.name() == "test") {
96-
let did = self.0.hir.body_owner_def_id(body_id);
96+
let did = self.0.hir().body_owner_def_id(body_id);
9797
println!("running test: {}", self.0.def_path_debug_str(did));
9898
miri::eval_main(self.0, did, /*validate*/true);
9999
self.1.session.abort_if_errors();
@@ -105,7 +105,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
105105
}
106106
state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(tcx, state));
107107
} else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
108-
let entry_def_id = tcx.hir.local_def_id(entry_node_id);
108+
let entry_def_id = tcx.hir().local_def_id(entry_node_id);
109109
miri::eval_main(tcx, entry_def_id, /*validate*/true);
110110

111111
state.session.abort_if_errors();

src/bin/miri.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ fn after_analysis<'a, 'tcx>(
128128
attr.name() == "test"
129129
})
130130
{
131-
let did = self.tcx.hir.body_owner_def_id(body_id);
131+
let did = self.tcx.hir().body_owner_def_id(body_id);
132132
println!(
133133
"running test: {}",
134134
self.tcx.def_path_debug_str(did),
@@ -145,7 +145,7 @@ fn after_analysis<'a, 'tcx>(
145145
&mut Visitor { tcx, state, validate }
146146
);
147147
} else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
148-
let entry_def_id = tcx.hir.local_def_id(entry_node_id);
148+
let entry_def_id = tcx.hir().local_def_id(entry_node_id);
149149
miri::eval_main(tcx, entry_def_id, validate);
150150

151151
state.session.abort_if_errors();

src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
508508
fn retag(
509509
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
510510
fn_entry: bool,
511+
two_phase: bool,
511512
place: PlaceTy<'tcx, Borrow>,
512513
) -> EvalResult<'tcx> {
513514
if !ecx.tcx.sess.opts.debugging_opts.mir_emit_retag || !Self::enforce_validity(ecx) {
@@ -518,7 +519,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
518519
// uninitialized data.
519520
Ok(())
520521
} else {
521-
ecx.retag(fn_entry, place)
522+
ecx.retag(fn_entry, two_phase, place)
522523
}
523524
}
524525

src/stacked_borrows.rs

+23-11
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc::hir::{Mutability, MutMutable, MutImmutable};
88
use crate::{
99
EvalResult, EvalErrorKind, MiriEvalContext, HelpersEvalContextExt, Evaluator, MutValueVisitor,
1010
MemoryKind, MiriMemoryKind, RangeMap, AllocId, Allocation, AllocationExtra,
11-
Pointer, MemPlace, Scalar, Immediate, ImmTy, PlaceTy, MPlaceTy,
11+
Pointer, Immediate, ImmTy, PlaceTy, MPlaceTy,
1212
};
1313

1414
pub type Timestamp = u64;
@@ -539,19 +539,21 @@ pub trait EvalContextExt<'tcx> {
539539
size: Size,
540540
fn_barrier: bool,
541541
new_bor: Borrow
542-
) -> EvalResult<'tcx, Pointer<Borrow>>;
542+
) -> EvalResult<'tcx>;
543543

544544
/// Retag an indidual pointer, returning the retagged version.
545545
fn retag_reference(
546546
&mut self,
547547
ptr: ImmTy<'tcx, Borrow>,
548548
mutbl: Mutability,
549549
fn_barrier: bool,
550+
two_phase: bool,
550551
) -> EvalResult<'tcx, Immediate<Borrow>>;
551552

552553
fn retag(
553554
&mut self,
554555
fn_entry: bool,
556+
two_phase: bool,
555557
place: PlaceTy<'tcx, Borrow>
556558
) -> EvalResult<'tcx>;
557559

@@ -649,9 +651,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
649651
size: Size,
650652
fn_barrier: bool,
651653
new_bor: Borrow
652-
) -> EvalResult<'tcx, Pointer<Borrow>> {
654+
) -> EvalResult<'tcx> {
653655
let ptr = place.ptr.to_ptr()?;
654-
let new_ptr = Pointer::new_with_tag(ptr.alloc_id, ptr.offset, new_bor);
655656
let barrier = if fn_barrier { Some(self.frame().extra) } else { None };
656657
trace!("reborrow: Creating new reference for {:?} (pointee {}): {:?}",
657658
ptr, place.layout.ty, new_bor);
@@ -671,14 +672,15 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
671672
let kind = if new_bor.is_unique() { RefKind::Unique } else { RefKind::Raw };
672673
alloc.extra.reborrow(ptr, size, barrier, new_bor, kind)?;
673674
}
674-
Ok(new_ptr)
675+
Ok(())
675676
}
676677

677678
fn retag_reference(
678679
&mut self,
679680
val: ImmTy<'tcx, Borrow>,
680681
mutbl: Mutability,
681682
fn_barrier: bool,
683+
two_phase: bool,
682684
) -> EvalResult<'tcx, Immediate<Borrow>> {
683685
// We want a place for where the ptr *points to*, so we get one.
684686
let place = self.ref_to_mplace(val)?;
@@ -698,16 +700,25 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
698700
};
699701

700702
// Reborrow.
701-
let new_ptr = self.reborrow(place, size, fn_barrier, new_bor)?;
703+
self.reborrow(place, size, fn_barrier, new_bor)?;
704+
let new_place = place.with_tag(new_bor);
705+
// Handle two-phase borrows.
706+
if two_phase {
707+
assert!(mutbl == MutMutable, "two-phase shared borrows make no sense");
708+
// We immediately share it, to allow read accesses
709+
let two_phase_time = self.machine.stacked_borrows.increment_clock();
710+
let two_phase_bor = Borrow::Shr(Some(two_phase_time));
711+
self.reborrow(new_place, size, /*fn_barrier*/false, two_phase_bor)?;
712+
}
702713

703-
// Return new ptr
704-
let new_place = MemPlace { ptr: Scalar::Ptr(new_ptr), ..*place };
714+
// Return new ptr.
705715
Ok(new_place.to_ref())
706716
}
707717

708718
fn retag(
709719
&mut self,
710720
fn_entry: bool,
721+
two_phase: bool,
711722
place: PlaceTy<'tcx, Borrow>
712723
) -> EvalResult<'tcx> {
713724
// Determine mutability and whether to add a barrier.
@@ -730,19 +741,20 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
730741
if let Some((mutbl, barrier)) = qualify(place.layout.ty, fn_entry) {
731742
// fast path
732743
let val = self.read_immediate(self.place_to_op(place)?)?;
733-
let val = self.retag_reference(val, mutbl, barrier)?;
744+
let val = self.retag_reference(val, mutbl, barrier, two_phase)?;
734745
self.write_immediate(val, place)?;
735746
return Ok(());
736747
}
737748
let place = self.force_allocation(place)?;
738749

739-
let mut visitor = RetagVisitor { ecx: self, fn_entry };
750+
let mut visitor = RetagVisitor { ecx: self, fn_entry, two_phase };
740751
visitor.visit_value(place)?;
741752

742753
// The actual visitor
743754
struct RetagVisitor<'ecx, 'a, 'mir, 'tcx> {
744755
ecx: &'ecx mut MiriEvalContext<'a, 'mir, 'tcx>,
745756
fn_entry: bool,
757+
two_phase: bool,
746758
}
747759
impl<'ecx, 'a, 'mir, 'tcx>
748760
MutValueVisitor<'a, 'mir, 'tcx, Evaluator<'tcx>>
@@ -763,7 +775,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
763775
// making it useless.
764776
if let Some((mutbl, barrier)) = qualify(place.layout.ty, self.fn_entry) {
765777
let val = self.ecx.read_immediate(place.into())?;
766-
let val = self.ecx.retag_reference(val, mutbl, barrier)?;
778+
let val = self.ecx.retag_reference(val, mutbl, barrier, self.two_phase)?;
767779
self.ecx.write_immediate(val, place.into())?;
768780
}
769781
Ok(())

tests/compile-fail/validity/nonzero.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ pub(crate) struct NonZero<T>(pub(crate) T);
77

88
fn main() {
99
// Make sure that we detect this even when no function call is happening along the way
10-
let _x = Some(NonZero(0)); //~ ERROR encountered 0, but expected something greater or equal to 1
10+
let _x = Some(unsafe { NonZero(0) }); //~ ERROR encountered 0, but expected something greater or equal to 1
1111
}

tests/run-pass/2phase.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#![feature(nll)]
2+
3+
trait S: Sized {
4+
fn tpb(&mut self, _s: Self) {}
5+
}
6+
7+
impl S for i32 {}
8+
9+
fn two_phase1() {
10+
let mut x = 3;
11+
x.tpb(x);
12+
}
13+
14+
fn two_phase2() {
15+
let mut v = vec![];
16+
v.push(v.len());
17+
}
18+
19+
/*
20+
fn two_phase_overlapping1() {
21+
let mut x = vec![];
22+
let p = &x;
23+
x.push(p.len());
24+
}
25+
26+
fn two_phase_overlapping2() {
27+
use std::ops::AddAssign;
28+
let mut x = 1;
29+
let l = &x;
30+
x.add_assign(x + *l);
31+
}
32+
*/
33+
34+
fn match_two_phase() {
35+
let mut x = 3;
36+
match x {
37+
ref mut y if { let _val = x; let _val = *y; true } => {},
38+
_ => (),
39+
}
40+
}
41+
42+
fn with_interior_mutability() {
43+
use std::cell::Cell;
44+
45+
trait Thing: Sized {
46+
fn do_the_thing(&mut self, _s: i32) {}
47+
}
48+
49+
impl<T> Thing for Cell<T> {}
50+
51+
let mut x = Cell::new(1);
52+
let l = &x;
53+
x
54+
.do_the_thing({
55+
x.set(3);
56+
l.set(4);
57+
x.get() + l.get()
58+
})
59+
;
60+
}
61+
62+
fn main() {
63+
two_phase1();
64+
two_phase2();
65+
match_two_phase();
66+
with_interior_mutability();
67+
//FIXME: enable these, or remove them, depending on how https://github.com/rust-lang/rust/issues/56254 gets resolved
68+
//two_phase_overlapping1();
69+
//two_phase_overlapping2();
70+
}

0 commit comments

Comments
 (0)