rustc: add rooting, write-guards to slices etc
This commit is contained in:
parent
f3a6ea2643
commit
be08c3e514
|
@ -866,7 +866,18 @@ pub fn extract_variant_args(bcx: block,
|
|||
ExtractedBlock { vals: args, bcx: bcx }
|
||||
}
|
||||
|
||||
fn match_datum(bcx: block, val: ValueRef, pat_id: ast::node_id) -> Datum {
|
||||
//! Helper for converting from the ValueRef that we pass around in
|
||||
//! the match code, which is always by ref, into a Datum. Eventually
|
||||
//! we should just pass around a Datum and be done with it.
|
||||
|
||||
let ty = node_id_type(bcx, pat_id);
|
||||
Datum {val: val, ty: ty, mode: datum::ByRef, source: RevokeClean}
|
||||
}
|
||||
|
||||
|
||||
pub fn extract_vec_elems(bcx: block,
|
||||
pat_span: span,
|
||||
pat_id: ast::node_id,
|
||||
elem_count: uint,
|
||||
slice: Option<uint>,
|
||||
|
@ -874,9 +885,9 @@ pub fn extract_vec_elems(bcx: block,
|
|||
count: ValueRef)
|
||||
-> ExtractedBlock {
|
||||
let _icx = bcx.insn_ctxt("match::extract_vec_elems");
|
||||
let vec_datum = match_datum(bcx, val, pat_id);
|
||||
let (bcx, base, len) = vec_datum.get_vec_base_and_len(bcx, pat_span, pat_id);
|
||||
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
|
||||
let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
|
||||
let (base, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty);
|
||||
|
||||
let mut elems = do vec::from_fn(elem_count) |i| {
|
||||
match slice {
|
||||
|
@ -1308,10 +1319,14 @@ pub fn compile_submatch(bcx: block,
|
|||
vec::slice(vals, col + 1u, vals.len()));
|
||||
let ccx = *bcx.fcx.ccx;
|
||||
let mut pat_id = 0;
|
||||
let mut pat_span = dummy_sp();
|
||||
for vec::each(m) |br| {
|
||||
// Find a real id (we're adding placeholder wildcard patterns, but
|
||||
// each column is guaranteed to have at least one real pattern)
|
||||
if pat_id == 0 { pat_id = br.pats[col].id; }
|
||||
if pat_id == 0 {
|
||||
pat_id = br.pats[col].id;
|
||||
pat_span = br.pats[col].span;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are not matching against an `@T`, we should not be
|
||||
|
@ -1579,8 +1594,8 @@ pub fn compile_submatch(bcx: block,
|
|||
vec_len_ge(_, i) => Some(i),
|
||||
_ => None
|
||||
};
|
||||
let args = extract_vec_elems(opt_cx, pat_id, n, slice,
|
||||
val, test_val);
|
||||
let args = extract_vec_elems(opt_cx, pat_span, pat_id, n, slice,
|
||||
val, test_val);
|
||||
size = args.vals.len();
|
||||
unpacked = /*bad*/copy args.vals;
|
||||
opt_cx = args.bcx;
|
||||
|
|
|
@ -333,7 +333,7 @@ pub fn trans_fail_expr(bcx: block,
|
|||
bcx, expr::trans_to_datum(bcx, arg_expr));
|
||||
|
||||
if ty::type_is_str(arg_datum.ty) {
|
||||
let (lldata, _lllen) = arg_datum.get_base_and_len(bcx);
|
||||
let (lldata, _) = arg_datum.get_vec_base_and_len_no_root(bcx);
|
||||
return trans_fail_value(bcx, sp_opt, lldata);
|
||||
} else if bcx.unreachable || ty::type_is_bot(arg_datum.ty) {
|
||||
return bcx;
|
||||
|
|
|
@ -603,6 +603,8 @@ pub impl Datum {
|
|||
}
|
||||
|
||||
fn perform_write_guard(&self, bcx: block, span: span) -> block {
|
||||
debug!("perform_write_guard");
|
||||
|
||||
// Create scratch space, but do not root it.
|
||||
let llval = match self.mode {
|
||||
ByValue => self.val,
|
||||
|
@ -682,25 +684,10 @@ pub impl Datum {
|
|||
{
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
debug!("try_deref(expr_id=%d, derefs=%?, is_auto=%b, self=%?)",
|
||||
debug!("try_deref(expr_id=%?, derefs=%?, is_auto=%b, self=%?)",
|
||||
expr_id, derefs, is_auto, self.to_str(bcx.ccx()));
|
||||
let _indenter = indenter();
|
||||
|
||||
// root the autoderef'd value, if necessary:
|
||||
//
|
||||
// (Note: root'd values are always boxes)
|
||||
let key = root_map_key { id: expr_id, derefs: derefs };
|
||||
let bcx = match ccx.maps.root_map.find(&key) {
|
||||
None => bcx,
|
||||
Some(&root_info) => self.root(bcx, span, key, root_info)
|
||||
};
|
||||
|
||||
// Perform the write guard, if necessary.
|
||||
//
|
||||
// (Note: write-guarded values are always boxes)
|
||||
let bcx = if ccx.maps.write_guard_map.contains(&key) {
|
||||
self.perform_write_guard(bcx, span)
|
||||
} else { bcx };
|
||||
let bcx = self.root_and_write_guard(bcx, span, expr_id, derefs);
|
||||
|
||||
match ty::get(self.ty).sty {
|
||||
ty::ty_box(_) | ty::ty_uniq(_) => {
|
||||
|
@ -854,8 +841,53 @@ pub impl Datum {
|
|||
DatumBlock { bcx: bcx, datum: datum }
|
||||
}
|
||||
|
||||
fn get_base_and_len(&self, bcx: block) -> (ValueRef, ValueRef) {
|
||||
tvec::get_base_and_len(bcx, self.to_appropriate_llval(bcx), self.ty)
|
||||
fn root_and_write_guard(&self,
|
||||
mut bcx: block,
|
||||
span: span,
|
||||
expr_id: ast::node_id,
|
||||
derefs: uint) -> block {
|
||||
let key = root_map_key { id: expr_id, derefs: derefs };
|
||||
debug!("root_and_write_guard(key=%?)", key);
|
||||
|
||||
// root the autoderef'd value, if necessary:
|
||||
//
|
||||
// (Note: root'd values are always boxes)
|
||||
let ccx = bcx.ccx();
|
||||
bcx = match ccx.maps.root_map.find(&key) {
|
||||
None => bcx,
|
||||
Some(&root_info) => self.root(bcx, span, key, root_info)
|
||||
};
|
||||
|
||||
// Perform the write guard, if necessary.
|
||||
//
|
||||
// (Note: write-guarded values are always boxes)
|
||||
if ccx.maps.write_guard_map.contains(&key) {
|
||||
self.perform_write_guard(bcx, span)
|
||||
} else {
|
||||
bcx
|
||||
}
|
||||
}
|
||||
|
||||
fn get_vec_base_and_len(&self,
|
||||
mut bcx: block,
|
||||
span: span,
|
||||
expr_id: ast::node_id)
|
||||
-> (block, ValueRef, ValueRef) {
|
||||
//! Converts a vector into the slice pair. Performs rooting
|
||||
//! and write guards checks.
|
||||
|
||||
// only imp't for @[] and @str, but harmless
|
||||
bcx = self.root_and_write_guard(bcx, span, expr_id, 0);
|
||||
let (base, len) = self.get_vec_base_and_len_no_root(bcx);
|
||||
(bcx, base, len)
|
||||
}
|
||||
|
||||
fn get_vec_base_and_len_no_root(&self, bcx: block) -> (ValueRef, ValueRef) {
|
||||
//! Converts a vector into the slice pair. Des not root
|
||||
//! nor perform write guard checks.
|
||||
|
||||
let llval = self.to_appropriate_llval(bcx);
|
||||
tvec::get_base_and_len(bcx, llval, self.ty)
|
||||
}
|
||||
|
||||
fn to_result(&self, bcx: block) -> common::Result {
|
||||
|
|
|
@ -218,10 +218,10 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||
unpack_datum!(bcx, auto_ref(bcx, datum))
|
||||
}
|
||||
Some(AutoBorrowVec(*)) => {
|
||||
unpack_datum!(bcx, auto_slice(bcx, datum))
|
||||
unpack_datum!(bcx, auto_slice(bcx, expr, datum))
|
||||
}
|
||||
Some(AutoBorrowVecRef(*)) => {
|
||||
unpack_datum!(bcx, auto_slice_and_ref(bcx, datum))
|
||||
unpack_datum!(bcx, auto_slice_and_ref(bcx, expr, datum))
|
||||
}
|
||||
Some(AutoBorrowFn(*)) => {
|
||||
// currently, all closure types are
|
||||
|
@ -241,7 +241,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||
DatumBlock {bcx: bcx, datum: datum.to_rptr(bcx)}
|
||||
}
|
||||
|
||||
fn auto_slice(bcx: block, datum: Datum) -> DatumBlock {
|
||||
fn auto_slice(bcx: block, expr: @ast::expr, datum: Datum) -> DatumBlock {
|
||||
// This is not the most efficient thing possible; since slices
|
||||
// are two words it'd be better if this were compiled in
|
||||
// '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 {
|
|||
|
||||
let tcx = bcx.tcx();
|
||||
let unit_ty = ty::sequence_element_type(tcx, datum.ty);
|
||||
let (base, len) = datum.get_base_and_len(bcx);
|
||||
// NOTE prob need to distinguish "auto-slice" from explicit index?
|
||||
let (bcx, base, len) =
|
||||
datum.get_vec_base_and_len(bcx, expr.span, expr.id);
|
||||
|
||||
// this type may have a different region/mutability than the
|
||||
// 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 {
|
|||
DatumBlock {bcx: bcx, datum: scratch}
|
||||
}
|
||||
|
||||
fn auto_slice_and_ref(bcx: block, datum: Datum) -> DatumBlock {
|
||||
let DatumBlock { bcx, datum } = auto_slice(bcx, datum);
|
||||
fn auto_slice_and_ref(bcx: block,
|
||||
expr: @ast::expr,
|
||||
datum: Datum) -> DatumBlock {
|
||||
let DatumBlock { bcx, datum } = auto_slice(bcx, expr, datum);
|
||||
auto_ref(bcx, datum)
|
||||
}
|
||||
}
|
||||
|
@ -903,7 +907,8 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||
let scaled_ix = Mul(bcx, ix_val, vt.llunit_size);
|
||||
base::maybe_name_value(bcx.ccx(), scaled_ix, ~"scaled_ix");
|
||||
|
||||
let mut (base, len) = base_datum.get_base_and_len(bcx);
|
||||
let mut (bcx, base, len) =
|
||||
base_datum.get_vec_base_and_len(bcx, index_expr.span, index_expr.id);
|
||||
|
||||
if ty::type_is_str(base_ty) {
|
||||
// acccount for null terminator in the case of string
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// error-pattern:borrowed
|
||||
|
||||
// Test that write guards trigger when there is a write to a field
|
||||
// of a frozen structure.
|
||||
|
||||
struct S {
|
||||
x: int
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// error-pattern:borrowed
|
||||
|
||||
// Test that write guards trigger when there is a write to a directly
|
||||
// frozen @mut box.
|
||||
|
||||
fn main() {
|
||||
let x = @mut 3;
|
||||
let y: &mut int = x;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// error-pattern:borrowed
|
||||
|
||||
// Test that write guards trigger when mut box is frozen
|
||||
// as part of argument coercion.
|
||||
|
||||
fn f(_x: &int, y: @mut int) {
|
||||
*y = 2;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// error-pattern:borrowed
|
||||
|
||||
// Test that write guards trigger when there is a coercion to
|
||||
// a slice on the receiver of a method.
|
||||
|
||||
trait MyMutSlice {
|
||||
fn my_mut_slice(self) -> Self;
|
||||
}
|
||||
|
||||
impl<'self, T> MyMutSlice for &'self mut [T] {
|
||||
fn my_mut_slice(self) -> &'self mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
trait MySlice {
|
||||
fn my_slice(self) -> Self;
|
||||
}
|
||||
|
||||
impl<'self, T> MySlice for &'self [T] {
|
||||
fn my_slice(self) -> &'self [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn add(x:&mut [int], y:&[int])
|
||||
{
|
||||
x[0] = x[0] + y[0];
|
||||
}
|
||||
|
||||
pub fn main()
|
||||
{
|
||||
let z = @mut [1,2,3];
|
||||
let z2 = z;
|
||||
add(z.my_mut_slice(), z2.my_slice());
|
||||
print(fmt!("%d\n", z[0]));
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// error-pattern:borrowed
|
||||
|
||||
// Test that write guards trigger when arguments are coerced to slices.
|
||||
|
||||
fn add(x:&mut [int], y:&[int])
|
||||
{
|
||||
x[0] = x[0] + y[0];
|
||||
}
|
||||
|
||||
pub fn main()
|
||||
{
|
||||
let z = @mut [1,2,3];
|
||||
let z2 = z;
|
||||
add(z, z2);
|
||||
print(fmt!("%d\n", z[0]));
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// error-pattern:borrowed
|
||||
|
||||
// Test that write guards trigger when we are indexing into
|
||||
// an @mut vector.
|
||||
|
||||
fn add(x:&mut int, y:&int)
|
||||
{
|
||||
*x = *x + *y;
|
||||
}
|
||||
|
||||
pub fn main()
|
||||
{
|
||||
let z = @mut [1,2,3];
|
||||
let z2 = z;
|
||||
add(&mut z[0], &z2[0]);
|
||||
print(fmt!("%d\n", z[0]));
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// error-pattern:borrowed
|
||||
|
||||
// Test that arguments trigger when there are *two mutable* borrows
|
||||
// of indices.
|
||||
|
||||
fn add(x:&mut int, y:&mut int)
|
||||
{
|
||||
*x = *x + *y;
|
||||
}
|
||||
|
||||
pub fn main()
|
||||
{
|
||||
let z = @mut [1,2,3];
|
||||
let z2 = z;
|
||||
add(&mut z[0], &mut z2[0]);
|
||||
print(fmt!("%d\n", z[0]));
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Test that we can borrow the same @mut box twice, so long as both are imm.
|
||||
|
||||
fn add(x:&int, y:&int)
|
||||
{
|
||||
*x + *y;
|
||||
}
|
||||
|
||||
pub fn main()
|
||||
{
|
||||
let z = @mut [1,2,3];
|
||||
let z2 = z;
|
||||
add(&z[0], &z2[0]);
|
||||
print(fmt!("%d\n", z[0]));
|
||||
}
|
Loading…
Reference in New Issue