Skip to content

Commit be08c3e

Browse files
committed
rustc: add rooting, write-guards to slices etc
1 parent f3a6ea2 commit be08c3e

12 files changed

+194
-32
lines changed

src/librustc/middle/trans/_match.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -866,17 +866,28 @@ pub fn extract_variant_args(bcx: block,
866866
ExtractedBlock { vals: args, bcx: bcx }
867867
}
868868
869+
fn match_datum(bcx: block, val: ValueRef, pat_id: ast::node_id) -> Datum {
870+
//! Helper for converting from the ValueRef that we pass around in
871+
//! the match code, which is always by ref, into a Datum. Eventually
872+
//! we should just pass around a Datum and be done with it.
873+
874+
let ty = node_id_type(bcx, pat_id);
875+
Datum {val: val, ty: ty, mode: datum::ByRef, source: RevokeClean}
876+
}
877+
878+
869879
pub fn extract_vec_elems(bcx: block,
880+
pat_span: span,
870881
pat_id: ast::node_id,
871882
elem_count: uint,
872883
slice: Option<uint>,
873884
val: ValueRef,
874885
count: ValueRef)
875886
-> ExtractedBlock {
876887
let _icx = bcx.insn_ctxt("match::extract_vec_elems");
888+
let vec_datum = match_datum(bcx, val, pat_id);
889+
let (bcx, base, len) = vec_datum.get_vec_base_and_len(bcx, pat_span, pat_id);
877890
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
878-
let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
879-
let (base, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty);
880891
881892
let mut elems = do vec::from_fn(elem_count) |i| {
882893
match slice {
@@ -1308,10 +1319,14 @@ pub fn compile_submatch(bcx: block,
13081319
vec::slice(vals, col + 1u, vals.len()));
13091320
let ccx = *bcx.fcx.ccx;
13101321
let mut pat_id = 0;
1322+
let mut pat_span = dummy_sp();
13111323
for vec::each(m) |br| {
13121324
// Find a real id (we're adding placeholder wildcard patterns, but
13131325
// each column is guaranteed to have at least one real pattern)
1314-
if pat_id == 0 { pat_id = br.pats[col].id; }
1326+
if pat_id == 0 {
1327+
pat_id = br.pats[col].id;
1328+
pat_span = br.pats[col].span;
1329+
}
13151330
}
13161331
13171332
// If we are not matching against an `@T`, we should not be
@@ -1579,8 +1594,8 @@ pub fn compile_submatch(bcx: block,
15791594
vec_len_ge(_, i) => Some(i),
15801595
_ => None
15811596
};
1582-
let args = extract_vec_elems(opt_cx, pat_id, n, slice,
1583-
val, test_val);
1597+
let args = extract_vec_elems(opt_cx, pat_span, pat_id, n, slice,
1598+
val, test_val);
15841599
size = args.vals.len();
15851600
unpacked = /*bad*/copy args.vals;
15861601
opt_cx = args.bcx;

src/librustc/middle/trans/controlflow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ pub fn trans_fail_expr(bcx: block,
333333
bcx, expr::trans_to_datum(bcx, arg_expr));
334334
335335
if ty::type_is_str(arg_datum.ty) {
336-
let (lldata, _lllen) = arg_datum.get_base_and_len(bcx);
336+
let (lldata, _) = arg_datum.get_vec_base_and_len_no_root(bcx);
337337
return trans_fail_value(bcx, sp_opt, lldata);
338338
} else if bcx.unreachable || ty::type_is_bot(arg_datum.ty) {
339339
return bcx;

src/librustc/middle/trans/datum.rs

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,8 @@ pub impl Datum {
603603
}
604604

605605
fn perform_write_guard(&self, bcx: block, span: span) -> block {
606+
debug!("perform_write_guard");
607+
606608
// Create scratch space, but do not root it.
607609
let llval = match self.mode {
608610
ByValue => self.val,
@@ -682,25 +684,10 @@ pub impl Datum {
682684
{
683685
let ccx = bcx.ccx();
684686

685-
debug!("try_deref(expr_id=%d, derefs=%?, is_auto=%b, self=%?)",
687+
debug!("try_deref(expr_id=%?, derefs=%?, is_auto=%b, self=%?)",
686688
expr_id, derefs, is_auto, self.to_str(bcx.ccx()));
687-
let _indenter = indenter();
688-
689-
// root the autoderef'd value, if necessary:
690-
//
691-
// (Note: root'd values are always boxes)
692-
let key = root_map_key { id: expr_id, derefs: derefs };
693-
let bcx = match ccx.maps.root_map.find(&key) {
694-
None => bcx,
695-
Some(&root_info) => self.root(bcx, span, key, root_info)
696-
};
697689

698-
// Perform the write guard, if necessary.
699-
//
700-
// (Note: write-guarded values are always boxes)
701-
let bcx = if ccx.maps.write_guard_map.contains(&key) {
702-
self.perform_write_guard(bcx, span)
703-
} else { bcx };
690+
let bcx = self.root_and_write_guard(bcx, span, expr_id, derefs);
704691

705692
match ty::get(self.ty).sty {
706693
ty::ty_box(_) | ty::ty_uniq(_) => {
@@ -854,8 +841,53 @@ pub impl Datum {
854841
DatumBlock { bcx: bcx, datum: datum }
855842
}
856843

857-
fn get_base_and_len(&self, bcx: block) -> (ValueRef, ValueRef) {
858-
tvec::get_base_and_len(bcx, self.to_appropriate_llval(bcx), self.ty)
844+
fn root_and_write_guard(&self,
845+
mut bcx: block,
846+
span: span,
847+
expr_id: ast::node_id,
848+
derefs: uint) -> block {
849+
let key = root_map_key { id: expr_id, derefs: derefs };
850+
debug!("root_and_write_guard(key=%?)", key);
851+
852+
// root the autoderef'd value, if necessary:
853+
//
854+
// (Note: root'd values are always boxes)
855+
let ccx = bcx.ccx();
856+
bcx = match ccx.maps.root_map.find(&key) {
857+
None => bcx,
858+
Some(&root_info) => self.root(bcx, span, key, root_info)
859+
};
860+
861+
// Perform the write guard, if necessary.
862+
//
863+
// (Note: write-guarded values are always boxes)
864+
if ccx.maps.write_guard_map.contains(&key) {
865+
self.perform_write_guard(bcx, span)
866+
} else {
867+
bcx
868+
}
869+
}
870+
871+
fn get_vec_base_and_len(&self,
872+
mut bcx: block,
873+
span: span,
874+
expr_id: ast::node_id)
875+
-> (block, ValueRef, ValueRef) {
876+
//! Converts a vector into the slice pair. Performs rooting
877+
//! and write guards checks.
878+
879+
// only imp't for @[] and @str, but harmless
880+
bcx = self.root_and_write_guard(bcx, span, expr_id, 0);
881+
let (base, len) = self.get_vec_base_and_len_no_root(bcx);
882+
(bcx, base, len)
883+
}
884+
885+
fn get_vec_base_and_len_no_root(&self, bcx: block) -> (ValueRef, ValueRef) {
886+
//! Converts a vector into the slice pair. Des not root
887+
//! nor perform write guard checks.
888+
889+
let llval = self.to_appropriate_llval(bcx);
890+
tvec::get_base_and_len(bcx, llval, self.ty)
859891
}
860892

861893
fn to_result(&self, bcx: block) -> common::Result {

src/librustc/middle/trans/expr.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,10 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
218218
unpack_datum!(bcx, auto_ref(bcx, datum))
219219
}
220220
Some(AutoBorrowVec(*)) => {
221-
unpack_datum!(bcx, auto_slice(bcx, datum))
221+
unpack_datum!(bcx, auto_slice(bcx, expr, datum))
222222
}
223223
Some(AutoBorrowVecRef(*)) => {
224-
unpack_datum!(bcx, auto_slice_and_ref(bcx, datum))
224+
unpack_datum!(bcx, auto_slice_and_ref(bcx, expr, datum))
225225
}
226226
Some(AutoBorrowFn(*)) => {
227227
// currently, all closure types are
@@ -241,7 +241,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
241241
DatumBlock {bcx: bcx, datum: datum.to_rptr(bcx)}
242242
}
243243

244-
fn auto_slice(bcx: block, datum: Datum) -> DatumBlock {
244+
fn auto_slice(bcx: block, expr: @ast::expr, datum: Datum) -> DatumBlock {
245245
// This is not the most efficient thing possible; since slices
246246
// are two words it'd be better if this were compiled in
247247
// 'dest' mode, but I can't find a nice way to structure the
@@ -250,7 +250,9 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
250250

251251
let tcx = bcx.tcx();
252252
let unit_ty = ty::sequence_element_type(tcx, datum.ty);
253-
let (base, len) = datum.get_base_and_len(bcx);
253+
// NOTE prob need to distinguish "auto-slice" from explicit index?
254+
let (bcx, base, len) =
255+
datum.get_vec_base_and_len(bcx, expr.span, expr.id);
254256

255257
// this type may have a different region/mutability than the
256258
// real one, but it will have the same runtime representation
@@ -283,8 +285,10 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
283285
DatumBlock {bcx: bcx, datum: scratch}
284286
}
285287

286-
fn auto_slice_and_ref(bcx: block, datum: Datum) -> DatumBlock {
287-
let DatumBlock { bcx, datum } = auto_slice(bcx, datum);
288+
fn auto_slice_and_ref(bcx: block,
289+
expr: @ast::expr,
290+
datum: Datum) -> DatumBlock {
291+
let DatumBlock { bcx, datum } = auto_slice(bcx, expr, datum);
288292
auto_ref(bcx, datum)
289293
}
290294
}
@@ -903,7 +907,8 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
903907
let scaled_ix = Mul(bcx, ix_val, vt.llunit_size);
904908
base::maybe_name_value(bcx.ccx(), scaled_ix, ~"scaled_ix");
905909

906-
let mut (base, len) = base_datum.get_base_and_len(bcx);
910+
let mut (bcx, base, len) =
911+
base_datum.get_vec_base_and_len(bcx, index_expr.span, index_expr.id);
907912

908913
if ty::type_is_str(base_ty) {
909914
// acccount for null terminator in the case of string

src/test/run-fail/borrowck-wg-fail-2.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// error-pattern:borrowed
22

3+
// Test that write guards trigger when there is a write to a field
4+
// of a frozen structure.
5+
36
struct S {
47
x: int
58
}

src/test/run-fail/borrowck-wg-fail-3.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// error-pattern:borrowed
22

3+
// Test that write guards trigger when there is a write to a directly
4+
// frozen @mut box.
5+
36
fn main() {
47
let x = @mut 3;
58
let y: &mut int = x;

src/test/run-fail/borrowck-wg-fail.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// error-pattern:borrowed
22

3+
// Test that write guards trigger when mut box is frozen
4+
// as part of argument coercion.
5+
36
fn f(_x: &int, y: @mut int) {
47
*y = 2;
58
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// error-pattern:borrowed
2+
3+
// Test that write guards trigger when there is a coercion to
4+
// a slice on the receiver of a method.
5+
6+
trait MyMutSlice {
7+
fn my_mut_slice(self) -> Self;
8+
}
9+
10+
impl<'self, T> MyMutSlice for &'self mut [T] {
11+
fn my_mut_slice(self) -> &'self mut [T] {
12+
self
13+
}
14+
}
15+
16+
trait MySlice {
17+
fn my_slice(self) -> Self;
18+
}
19+
20+
impl<'self, T> MySlice for &'self [T] {
21+
fn my_slice(self) -> &'self [T] {
22+
self
23+
}
24+
}
25+
26+
fn add(x:&mut [int], y:&[int])
27+
{
28+
x[0] = x[0] + y[0];
29+
}
30+
31+
pub fn main()
32+
{
33+
let z = @mut [1,2,3];
34+
let z2 = z;
35+
add(z.my_mut_slice(), z2.my_slice());
36+
print(fmt!("%d\n", z[0]));
37+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// error-pattern:borrowed
2+
3+
// Test that write guards trigger when arguments are coerced to slices.
4+
5+
fn add(x:&mut [int], y:&[int])
6+
{
7+
x[0] = x[0] + y[0];
8+
}
9+
10+
pub fn main()
11+
{
12+
let z = @mut [1,2,3];
13+
let z2 = z;
14+
add(z, z2);
15+
print(fmt!("%d\n", z[0]));
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// error-pattern:borrowed
2+
3+
// Test that write guards trigger when we are indexing into
4+
// an @mut vector.
5+
6+
fn add(x:&mut int, y:&int)
7+
{
8+
*x = *x + *y;
9+
}
10+
11+
pub fn main()
12+
{
13+
let z = @mut [1,2,3];
14+
let z2 = z;
15+
add(&mut z[0], &z2[0]);
16+
print(fmt!("%d\n", z[0]));
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// error-pattern:borrowed
2+
3+
// Test that arguments trigger when there are *two mutable* borrows
4+
// of indices.
5+
6+
fn add(x:&mut int, y:&mut int)
7+
{
8+
*x = *x + *y;
9+
}
10+
11+
pub fn main()
12+
{
13+
let z = @mut [1,2,3];
14+
let z2 = z;
15+
add(&mut z[0], &mut z2[0]);
16+
print(fmt!("%d\n", z[0]));
17+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Test that we can borrow the same @mut box twice, so long as both are imm.
2+
3+
fn add(x:&int, y:&int)
4+
{
5+
*x + *y;
6+
}
7+
8+
pub fn main()
9+
{
10+
let z = @mut [1,2,3];
11+
let z2 = z;
12+
add(&z[0], &z2[0]);
13+
print(fmt!("%d\n", z[0]));
14+
}

0 commit comments

Comments
 (0)