diff options
| -rw-r--r-- | src/libcore/at_vec.rs | 18 | ||||
| -rw-r--r-- | src/libcore/vec.rs | 49 | ||||
| -rw-r--r-- | src/libstd/arena.rs | 115 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 1 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/check.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-lend-args.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/deprecated-mode-fn-arg.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-511.rs | 6 | ||||
| -rw-r--r-- | src/test/compile-fail/liveness-dead.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/liveness-move-from-args.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/liveness-unused.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/mutable-arguments.rs | 12 | ||||
| -rw-r--r-- | src/test/run-pass/intrinsic-move-val.rs | 6 |
13 files changed, 204 insertions, 23 deletions
diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs index 5e1111c20d3..8c023a7cb4c 100644 --- a/src/libcore/at_vec.rs +++ b/src/libcore/at_vec.rs @@ -21,7 +21,11 @@ extern mod rustrt { #[abi = "rust-intrinsic"] extern mod rusti { #[legacy_exports]; + #[cfg(stage0)] fn move_val_init<T>(&dst: T, -src: T); + #[cfg(stage1)] + #[cfg(stage2)] + fn move_val_init<T>(dst: &mut T, -src: T); } /// Returns the number of elements the vector can hold without reallocating @@ -176,7 +180,9 @@ pub mod raw { push_slow(v, move initval); } } + // This doesn't bother to make sure we have space. + #[cfg(stage0)] #[inline(always)] // really pretty please pub unsafe fn push_fast<T>(v: &mut @[const T], initval: T) { let repr: **VecRepr = ::cast::reinterpret_cast(&v); @@ -186,6 +192,18 @@ pub mod raw { let p = ptr::offset(p, fill) as *mut T; rusti::move_val_init(*p, move initval); } + // This doesn't bother to make sure we have space. + #[cfg(stage1)] + #[cfg(stage2)] + #[inline(always)] // really pretty please + pub unsafe fn push_fast<T>(v: &mut @[const T], initval: T) { + let repr: **VecRepr = ::cast::reinterpret_cast(&v); + let fill = (**repr).unboxed.fill; + (**repr).unboxed.fill += sys::size_of::<T>(); + let p = addr_of(&((**repr).unboxed.data)); + let p = ptr::offset(p, fill) as *mut T; + rusti::move_val_init(&mut(*p), move initval); + } pub unsafe fn push_slow<T>(v: &mut @[const T], initval: T) { reserve_at_least(v, v.len() + 1u); diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index a157071c955..ce1193aa730 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -18,9 +18,14 @@ extern mod rustrt { #[abi = "rust-intrinsic"] extern mod rusti { + #[cfg(stage0)] fn move_val_init<T>(&dst: T, -src: T); + #[cfg(stage1)] + #[cfg(stage2)] + fn move_val_init<T>(dst: &mut T, -src: T); } + /// Returns true if a vector contains no elements pub pure fn is_empty<T>(v: &[const T]) -> bool { as_const_buf(v, |_p, len| len == 0u) @@ -98,6 +103,7 @@ pub pure fn len<T>(v: &[const T]) -> uint { * Creates an immutable vector of size `n_elts` and initializes the elements * to the value returned by the function `op`. */ +#[cfg(stage0)] pub pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> ~[T] { unsafe { let mut v = with_capacity(n_elts); @@ -112,6 +118,22 @@ pub pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> ~[T] { return move v; } } +#[cfg(stage1)] +#[cfg(stage2)] +pub pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> ~[T] { + unsafe { + let mut v = with_capacity(n_elts); + do as_mut_buf(v) |p, _len| { + let mut i: uint = 0u; + while i < n_elts { + rusti::move_val_init(&mut(*ptr::mut_offset(p, i)), op(i)); + i += 1u; + } + } + raw::set_len(&mut v, n_elts); + return move v; + } +} /** * Creates and initializes an immutable vector. @@ -481,6 +503,7 @@ pub fn push<T>(v: &mut ~[T], initval: T) { } } +#[cfg(stage0)] // This doesn't bother to make sure we have space. #[inline(always)] // really pretty please unsafe fn push_fast<T>(v: &mut ~[T], initval: T) { @@ -491,6 +514,18 @@ unsafe fn push_fast<T>(v: &mut ~[T], initval: T) { let p = ptr::offset(p, fill) as *mut T; rusti::move_val_init(*p, move initval); } +#[cfg(stage1)] +#[cfg(stage2)] +// This doesn't bother to make sure we have space. +#[inline(always)] // really pretty please +unsafe fn push_fast<T>(v: &mut ~[T], initval: T) { + let repr: **raw::VecRepr = ::cast::transmute(v); + let fill = (**repr).unboxed.fill; + (**repr).unboxed.fill += sys::size_of::<T>(); + let p = addr_of(&((**repr).unboxed.data)); + let p = ptr::offset(p, fill) as *mut T; + rusti::move_val_init(&mut(*p), move initval); +} #[inline(never)] fn push_slow<T>(v: &mut ~[T], initval: T) { @@ -1758,6 +1793,18 @@ pub mod raw { as_const_buf(v, |p, _len| *ptr::const_offset(p, i)) } + #[cfg(stage0)] + #[inline(always)] + pub unsafe fn init_elem<T>(v: &[mut T], i: uint, val: T) { + let mut box = Some(move val); + do as_mut_buf(v) |p, _len| { + let mut box2 = None; + box2 <-> box; + rusti::move_val_init(*ptr::mut_offset(p, i), + option::unwrap(move box2)); + } + } + #[cfg(stage1)] /** * Unchecked vector index assignment. Does not drop the * old value and hence is only suitable when the vector @@ -1769,7 +1816,7 @@ pub mod raw { do as_mut_buf(v) |p, _len| { let mut box2 = None; box2 <-> box; - rusti::move_val_init(*ptr::mut_offset(p, i), + rusti::move_val_init(&mut(*ptr::mut_offset(p, i)), option::unwrap(move box2)); } } diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs index 4d2b910fa85..69478b3e731 100644 --- a/src/libstd/arena.rs +++ b/src/libstd/arena.rs @@ -31,9 +31,14 @@ use libc::size_t; #[abi = "rust-intrinsic"] extern mod rusti { + #[cfg(stage0)] fn move_val_init<T>(&dst: T, -src: T); + #[cfg(stage1)] + #[cfg(stage2)] + fn move_val_init<T>(dst: &mut T, -src: T); fn needs_drop<T>() -> bool; } + extern mod rustrt { #[rust_stack] fn rust_call_tydesc_glue(root: *u8, tydesc: *TypeDesc, field: size_t); @@ -127,6 +132,8 @@ unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) { (reinterpret_cast(&(p & !1)), p & 1 == 1) } +// tjc: Can get rid of the duplication post-snapshot +#[cfg(stage0)] // The duplication between the POD and non-POD functions is annoying. impl &Arena { // Functions for the POD part of the arena @@ -234,6 +241,114 @@ impl &Arena { } else { self.alloc_nonpod(op) } } } +#[cfg(stage1)] +#[cfg(stage2)] +impl &Arena { + // Functions for the POD part of the arena + fn alloc_pod_grow(n_bytes: uint, align: uint) -> *u8 { + // Allocate a new chunk. + let chunk_size = at_vec::capacity(self.pod_head.data); + let new_min_chunk_size = uint::max(n_bytes, chunk_size); + self.chunks = @Cons(copy self.pod_head, self.chunks); + self.pod_head = + chunk(uint::next_power_of_two(new_min_chunk_size + 1u), true); + + return self.alloc_pod_inner(n_bytes, align); + } + + #[inline(always)] + fn alloc_pod_inner(n_bytes: uint, align: uint) -> *u8 { + let head = &mut self.pod_head; + + let start = round_up_to(head.fill, align); + let end = start + n_bytes; + if end > at_vec::capacity(head.data) { + return self.alloc_pod_grow(n_bytes, align); + } + head.fill = end; + + //debug!("idx = %u, size = %u, align = %u, fill = %u", + // start, n_bytes, align, head.fill); + + unsafe { + ptr::offset(vec::raw::to_ptr(head.data), start) + } + } + + #[inline(always)] + fn alloc_pod<T>(op: fn() -> T) -> &self/T { + unsafe { + let tydesc = sys::get_type_desc::<T>(); + let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align); + let ptr: *mut T = reinterpret_cast(&ptr); + rusti::move_val_init(&mut (*ptr), op()); + return reinterpret_cast(&ptr); + } + } + + // Functions for the non-POD part of the arena + fn alloc_nonpod_grow(n_bytes: uint, align: uint) -> (*u8, *u8) { + // Allocate a new chunk. + let chunk_size = at_vec::capacity(self.head.data); + let new_min_chunk_size = uint::max(n_bytes, chunk_size); + self.chunks = @Cons(copy self.head, self.chunks); + self.head = + chunk(uint::next_power_of_two(new_min_chunk_size + 1u), false); + + return self.alloc_nonpod_inner(n_bytes, align); + } + + #[inline(always)] + fn alloc_nonpod_inner(n_bytes: uint, align: uint) -> (*u8, *u8) { + let head = &mut self.head; + + let tydesc_start = head.fill; + let after_tydesc = head.fill + sys::size_of::<*TypeDesc>(); + let start = round_up_to(after_tydesc, align); + let end = start + n_bytes; + if end > at_vec::capacity(head.data) { + return self.alloc_nonpod_grow(n_bytes, align); + } + head.fill = round_up_to(end, sys::pref_align_of::<*TypeDesc>()); + + //debug!("idx = %u, size = %u, align = %u, fill = %u", + // start, n_bytes, align, head.fill); + + unsafe { + let buf = vec::raw::to_ptr(head.data); + return (ptr::offset(buf, tydesc_start), ptr::offset(buf, start)); + } + } + + #[inline(always)] + fn alloc_nonpod<T>(op: fn() -> T) -> &self/T { + unsafe { + let tydesc = sys::get_type_desc::<T>(); + let (ty_ptr, ptr) = + self.alloc_nonpod_inner((*tydesc).size, (*tydesc).align); + let ty_ptr: *mut uint = reinterpret_cast(&ty_ptr); + let ptr: *mut T = reinterpret_cast(&ptr); + // Write in our tydesc along with a bit indicating that it + // has *not* been initialized yet. + *ty_ptr = reinterpret_cast(&tydesc); + // Actually initialize it + rusti::move_val_init(&mut(*ptr), op()); + // Now that we are done, update the tydesc to indicate that + // the object is there. + *ty_ptr = bitpack_tydesc_ptr(tydesc, true); + + return reinterpret_cast(&ptr); + } + } + + // The external interface + #[inline(always)] + fn alloc<T>(op: fn() -> T) -> &self/T { + if !rusti::needs_drop::<T>() { + self.alloc_pod(op) + } else { self.alloc_nonpod(op) } + } +} #[test] fn test_arena_destructors() { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8860d1b5cea..1a87d7fed69 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -570,6 +570,7 @@ impl parser { fn parse_arg_mode() -> mode { if self.eat(token::BINOP(token::AND)) { + self.warn(~"Obsolete syntax has no effect"); expl(by_mutbl_ref) } else if self.eat(token::BINOP(token::MINUS)) { expl(by_move) diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 368b69cafab..7cc2c8b0ad7 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2601,7 +2601,9 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { ~"addr_of" => (1u, ~[arg(ast::by_ref, param(ccx, 0u))], ty::mk_imm_ptr(tcx, param(ccx, 0u))), ~"move_val" | ~"move_val_init" => { - (1u, ~[arg(ast::by_mutbl_ref, param(ccx, 0u)), + (1u, ~[arg(ast::by_copy, + ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), + param(ccx, 0u))), arg(ast::by_move, param(ccx, 0u))], ty::mk_nil(tcx)) } diff --git a/src/test/compile-fail/borrowck-lend-args.rs b/src/test/compile-fail/borrowck-lend-args.rs index 3cb7009ee27..79f52b93612 100644 --- a/src/test/compile-fail/borrowck-lend-args.rs +++ b/src/test/compile-fail/borrowck-lend-args.rs @@ -4,8 +4,8 @@ fn borrow_from_arg_imm_ref(&&v: ~int) { borrow(v); } -fn borrow_from_arg_mut_ref(&v: ~int) { - borrow(v); //~ ERROR illegal borrow unless pure +fn borrow_from_arg_mut_ref(v: &mut ~int) { + borrow(*v); //~ ERROR illegal borrow unless pure //~^ NOTE impure due to access to impure function } diff --git a/src/test/compile-fail/deprecated-mode-fn-arg.rs b/src/test/compile-fail/deprecated-mode-fn-arg.rs index 5afffb59dfc..2c20e604f50 100644 --- a/src/test/compile-fail/deprecated-mode-fn-arg.rs +++ b/src/test/compile-fail/deprecated-mode-fn-arg.rs @@ -1,9 +1,11 @@ #[forbid(deprecated_mode)]; fn foo(_f: fn(&i: int)) { //~ ERROR explicit mode + //~^ WARNING Obsolete syntax has no effect } type Bar = fn(&i: int); //~ ERROR explicit mode + //~^ WARNING Obsolete syntax has no effect fn main() { } \ No newline at end of file diff --git a/src/test/compile-fail/issue-511.rs b/src/test/compile-fail/issue-511.rs index a3498dd1968..02a3082dc10 100644 --- a/src/test/compile-fail/issue-511.rs +++ b/src/test/compile-fail/issue-511.rs @@ -1,11 +1,11 @@ extern mod std; use cmp::Eq; -fn f<T:Eq>(&o: Option<T>) { - assert o == option::None; +fn f<T:Eq>(o: &mut Option<T>) { + assert *o == option::None; } fn main() { - f::<int>(option::None); + f::<int>(&mut option::None); //~^ ERROR illegal borrow: creating mutable alias to static item } diff --git a/src/test/compile-fail/liveness-dead.rs b/src/test/compile-fail/liveness-dead.rs index a115d7c4e34..834457940be 100644 --- a/src/test/compile-fail/liveness-dead.rs +++ b/src/test/compile-fail/liveness-dead.rs @@ -1,5 +1,5 @@ -fn f1(&x: int) { - x = 1; // no error +fn f1(x: &mut int) { + *x = 1; // no error } fn f2() { diff --git a/src/test/compile-fail/liveness-move-from-args.rs b/src/test/compile-fail/liveness-move-from-args.rs index 27e7e51b405..27e9d3b60dc 100644 --- a/src/test/compile-fail/liveness-move-from-args.rs +++ b/src/test/compile-fail/liveness-move-from-args.rs @@ -4,10 +4,6 @@ fn from_by_value_arg(++x: int) { take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode } -fn from_by_mut_ref_arg(&x: int) { - take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode -} - fn from_by_ref_arg(&&x: int) { take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode } diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index 7db02897112..8b2fef7cd35 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -2,7 +2,7 @@ fn f1(x: int) { //~^ WARNING unused variable: `x` } -fn f1b(&x: int) { +fn f1b(x: &mut int) { //~^ WARNING unused variable: `x` } diff --git a/src/test/compile-fail/mutable-arguments.rs b/src/test/compile-fail/mutable-arguments.rs index 4fcb73e8516..d84c9401e25 100644 --- a/src/test/compile-fail/mutable-arguments.rs +++ b/src/test/compile-fail/mutable-arguments.rs @@ -1,28 +1,28 @@ // Note: it would be nice to give fewer warnings in these cases. -fn mutate_by_mut_ref(&x: uint) { - x = 0u; +fn mutate_by_mut_ref(x: &mut uint) { + *x = 0; } fn mutate_by_ref(&&x: uint) { //~^ WARNING unused variable: `x` - x = 0u; //~ ERROR assigning to argument + x = 0; //~ ERROR assigning to argument } fn mutate_by_val(++x: uint) { //~^ WARNING unused variable: `x` - x = 0u; //~ ERROR assigning to argument + x = 0; //~ ERROR assigning to argument } fn mutate_by_copy(+x: uint) { //~^ WARNING unused variable: `x` - x = 0u; //~ ERROR assigning to argument + x = 0; //~ ERROR assigning to argument //~^ WARNING value assigned to `x` is never read } fn mutate_by_move(-x: uint) { //~^ WARNING unused variable: `x` - x = 0u; //~ ERROR assigning to argument + x = 0; //~ ERROR assigning to argument //~^ WARNING value assigned to `x` is never read } diff --git a/src/test/run-pass/intrinsic-move-val.rs b/src/test/run-pass/intrinsic-move-val.rs index b7f2115f45d..683321aac3d 100644 --- a/src/test/run-pass/intrinsic-move-val.rs +++ b/src/test/run-pass/intrinsic-move-val.rs @@ -1,13 +1,13 @@ #[abi = "rust-intrinsic"] extern mod rusti { #[legacy_exports]; - fn move_val_init<T>(&dst: T, -src: T); - fn move_val<T>(&dst: T, -src: T); + fn move_val_init<T>(dst: &mut T, -src: T); + fn move_val<T>(dst: &mut T, -src: T); } fn main() { let mut x = @1; let mut y = @2; - rusti::move_val(y, x); + rusti::move_val(&mut y, x); assert *y == 1; } \ No newline at end of file |
