Allow moving out of mutable unsafe pointers
This makes it possible to de-initialize values anywhere in memory, which is needed, for example, for a fast imlementation of vec::pop.
This commit is contained in:
parent
dc55c06aa3
commit
362625008a
2 changed files with 20 additions and 10 deletions
|
@ -5,7 +5,7 @@ import syntax::visit;
|
||||||
import syntax::ast_util;
|
import syntax::ast_util;
|
||||||
import driver::session::session;
|
import driver::session::session;
|
||||||
|
|
||||||
enum deref_t { unbox, field, index, }
|
enum deref_t { unbox(bool), field, index, }
|
||||||
|
|
||||||
type deref = @{mut: bool, kind: deref_t, outer_t: ty::t};
|
type deref = @{mut: bool, kind: deref_t, outer_t: ty::t};
|
||||||
|
|
||||||
|
@ -20,15 +20,15 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
|
||||||
while true {
|
while true {
|
||||||
alt ty::struct(tcx, t) {
|
alt ty::struct(tcx, t) {
|
||||||
ty::ty_box(mt) {
|
ty::ty_box(mt) {
|
||||||
ds += [@{mut: mt.mut == mut, kind: unbox, outer_t: t}];
|
ds += [@{mut: mt.mut == mut, kind: unbox(false), outer_t: t}];
|
||||||
t = mt.ty;
|
t = mt.ty;
|
||||||
}
|
}
|
||||||
ty::ty_uniq(mt) {
|
ty::ty_uniq(mt) {
|
||||||
ds += [@{mut: mt.mut == mut, kind: unbox, outer_t: t}];
|
ds += [@{mut: mt.mut == mut, kind: unbox(false), outer_t: t}];
|
||||||
t = mt.ty;
|
t = mt.ty;
|
||||||
}
|
}
|
||||||
ty::ty_res(_, inner, tps) {
|
ty::ty_res(_, inner, tps) {
|
||||||
ds += [@{mut: false, kind: unbox, outer_t: t}];
|
ds += [@{mut: false, kind: unbox(false), outer_t: t}];
|
||||||
t = ty::substitute_type_params(tcx, tps, inner);
|
t = ty::substitute_type_params(tcx, tps, inner);
|
||||||
}
|
}
|
||||||
ty::ty_enum(did, tps) {
|
ty::ty_enum(did, tps) {
|
||||||
|
@ -37,7 +37,7 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
|
||||||
vec::len(variants[0].args) != 1u {
|
vec::len(variants[0].args) != 1u {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ds += [@{mut: false, kind: unbox, outer_t: t}];
|
ds += [@{mut: false, kind: unbox(false), outer_t: t}];
|
||||||
t = ty::substitute_type_params(tcx, tps, variants[0].args[0]);
|
t = ty::substitute_type_params(tcx, tps, variants[0].args[0]);
|
||||||
}
|
}
|
||||||
_ { break; }
|
_ { break; }
|
||||||
|
@ -85,15 +85,16 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
|
||||||
expr_unary(op, base) {
|
expr_unary(op, base) {
|
||||||
if op == deref {
|
if op == deref {
|
||||||
let base_t = ty::expr_ty(tcx, base);
|
let base_t = ty::expr_ty(tcx, base);
|
||||||
let is_mut = false;
|
let is_mut = false, ptr = false;
|
||||||
alt ty::struct(tcx, base_t) {
|
alt ty::struct(tcx, base_t) {
|
||||||
ty::ty_box(mt) { is_mut = mt.mut == mut; }
|
ty::ty_box(mt) { is_mut = mt.mut == mut; }
|
||||||
ty::ty_uniq(mt) { is_mut = mt.mut == mut; }
|
ty::ty_uniq(mt) { is_mut = mt.mut == mut; }
|
||||||
ty::ty_res(_, _, _) { }
|
ty::ty_res(_, _, _) { }
|
||||||
ty::ty_enum(_, _) { }
|
ty::ty_enum(_, _) { }
|
||||||
ty::ty_ptr(mt) { is_mut = mt.mut == mut; }
|
ty::ty_ptr(mt) { is_mut = mt.mut == mut; ptr = true; }
|
||||||
}
|
}
|
||||||
ds += [@{mut: is_mut, kind: unbox, outer_t: base_t}];
|
ds += [@{mut: is_mut, kind: unbox(ptr && is_mut),
|
||||||
|
outer_t: base_t}];
|
||||||
ex = base;
|
ex = base;
|
||||||
} else { break; }
|
} else { break; }
|
||||||
}
|
}
|
||||||
|
@ -187,7 +188,7 @@ fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
|
||||||
} else if !root.ds[0].mut {
|
} else if !root.ds[0].mut {
|
||||||
let name =
|
let name =
|
||||||
alt root.ds[0].kind {
|
alt root.ds[0].kind {
|
||||||
mut::unbox { "immutable box" }
|
mut::unbox(_) { "immutable box" }
|
||||||
mut::field { "immutable field" }
|
mut::field { "immutable field" }
|
||||||
mut::index { "immutable vec content" }
|
mut::index { "immutable vec content" }
|
||||||
};
|
};
|
||||||
|
@ -212,7 +213,8 @@ fn check_move_rhs(cx: @ctx, src: @expr) {
|
||||||
let root = expr_root(cx.tcx, src, false);
|
let root = expr_root(cx.tcx, src, false);
|
||||||
|
|
||||||
// Not a path and no-derefs means this is a temporary.
|
// Not a path and no-derefs means this is a temporary.
|
||||||
if vec::len(*root.ds) != 0u {
|
if vec::len(*root.ds) != 0u &&
|
||||||
|
root.ds[vec::len(*root.ds) - 1u].kind != unbox(true) {
|
||||||
cx.tcx.sess.span_err(src.span, "moving out of a data structure");
|
cx.tcx.sess.span_err(src.span, "moving out of a data structure");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,6 +307,14 @@ fn pop<T: copy>(&v: [const T]) -> T {
|
||||||
let e = v[ln];
|
let e = v[ln];
|
||||||
v = slice(v, 0u, ln);
|
v = slice(v, 0u, ln);
|
||||||
ret e;
|
ret e;
|
||||||
|
// FIXME use this implementation after the next snapshot (27.01.2012)
|
||||||
|
/* let new_ln = len(v) - 1u;
|
||||||
|
assert (new_ln > 0u);
|
||||||
|
let valptr = ptr::mut_addr_of(v[new_ln]);
|
||||||
|
let val <- *valptr;
|
||||||
|
unsafe::set_len(v, new_ln);
|
||||||
|
val
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Reference in a new issue