diff --git a/doc/rust.md b/doc/rust.md index f64877a69ba97..6be428ef27908 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -214,7 +214,7 @@ false fn for if impl let loop match mod mut -priv pub pure +priv pub ref return self static struct super true trait type @@ -936,7 +936,6 @@ Specifically, the following operations are considered unsafe: - Dereferencing a [raw pointer](#pointer-types). - Casting a [raw pointer](#pointer-types) to a safe pointer type. - - Breaking the [purity-checking rules](#pure-functions) in a `pure` function. - Calling an unsafe function. ##### Unsafe blocks @@ -946,42 +945,6 @@ This facility exists because the static semantics of Rust are a necessary approx When a programmer has sufficient conviction that a sequence of unsafe operations is actually safe, they can encapsulate that sequence (taken as a whole) within an `unsafe` block. The compiler will consider uses of such code "safe", to the surrounding context. -#### Pure functions - -A pure function declaration is identical to a function declaration, except that -it is declared with the additional keyword `pure`. In addition, the typechecker -checks the body of a pure function with a restricted set of typechecking rules. -A pure function may only modify data owned by its own stack frame. -So, a pure function may modify a local variable allocated on the stack, but not a mutable reference that it takes as an argument. -A pure function may only call other pure functions, not general functions. - -An example of a pure function: - -~~~~ -pure fn lt_42(x: int) -> bool { - return (x < 42); -} -~~~~ - -Pure functions may call other pure functions: - -~~~~{.xfail-test} -pure fn pure_length(ls: List) -> uint { ... } - -pure fn nonempty_list(ls: List) -> bool { pure_length(ls) > 0u } -~~~~ - -These purity-checking rules approximate the concept of referential transparency: -that a call-expression could be rewritten with the literal-expression of its return value, without changing the meaning of the program. -Since they are an approximation, sometimes these rules are *too* restrictive. -Rust allows programmers to violate these rules using [`unsafe` blocks](#unsafe-blocks), which we already saw. -As with any `unsafe` block, those that violate static purity carry transfer the burden of safety-proof from the compiler to the programmer. -Programmers should exercise caution when breaking such rules. - -For more details on purity, see [the borrowed pointer tutorial][borrow]. - -[borrow]: tutorial-borrowed-ptr.html - #### Diverging functions A special kind of function can be declared with a `!` character where the @@ -1246,10 +1209,10 @@ For example: ~~~~ trait Num { - static pure fn from_int(n: int) -> Self; + static fn from_int(n: int) -> Self; } impl Num for float { - static pure fn from_int(n: int) -> float { n as float } + static fn from_int(n: int) -> float { n as float } } let x: float = Num::from_int(42); ~~~~ @@ -2643,7 +2606,7 @@ Raw pointers (`*`) ### Function types The function type-constructor `fn` forms new function types. A function type -consists of a set of function-type modifiers (`pure`, `unsafe`, `extern`, etc.), +consists of a set of function-type modifiers (`unsafe`, `extern`, etc.), a sequence of input slots and an output slot. An example of a `fn` type: diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md index e638579253fed..8e0ca297f657c 100644 --- a/doc/tutorial-borrowed-ptr.md +++ b/doc/tutorial-borrowed-ptr.md @@ -486,12 +486,12 @@ For example, we could write a subroutine like this: ~~~ struct Point {x: float, y: float} -fn get_x(p: &r/Point) -> &r/float { &p.x } +fn get_x(p: &'r Point) -> &'r float { &p.x } ~~~ Here, the function `get_x()` returns a pointer into the structure it -was given. The type of the parameter (`&r/Point`) and return type -(`&r/float`) both use a new syntactic form that we have not seen so +was given. The type of the parameter (`&'r Point`) and return type +(`&'r float`) both use a new syntactic form that we have not seen so far. Here the identifier `r` names the lifetime of the pointer explicitly. So in effect, this function declares that it takes a pointer with lifetime `r` and returns a pointer with that same @@ -572,8 +572,8 @@ function: # Rectangle(Point, Size) // upper-left, dimensions # } # fn compute_area(shape: &Shape) -> float { 0f } -fn select(shape: &r/Shape, threshold: float, - a: &r/T, b: &r/T) -> &r/T { +fn select(shape: &'r Shape, threshold: float, + a: &'r T, b: &'r T) -> &'r T { if compute_area(shape) > threshold {a} else {b} } ~~~ @@ -593,17 +593,17 @@ example: # } # fn compute_area(shape: &Shape) -> float { 0f } # fn select(shape: &Shape, threshold: float, -# a: &r/T, b: &r/T) -> &r/T { +# a: &'r T, b: &'r T) -> &'r T { # if compute_area(shape) > threshold {a} else {b} # } - // -+ r -fn select_based_on_unit_circle( // |-+ B - threshold: float, a: &r/T, b: &r/T) -> &r/T { // | | - // | | - let shape = Circle(Point {x: 0., y: 0.}, 1.); // | | - select(&shape, threshold, a, b) // | | -} // |-+ - // -+ + // -+ r +fn select_based_on_unit_circle( // |-+ B + threshold: float, a: &'r T, b: &'r T) -> &'r T { // | | + // | | + let shape = Circle(Point {x: 0., y: 0.}, 1.); // | | + select(&shape, threshold, a, b) // | | +} // |-+ + // -+ ~~~ In this call to `select()`, the lifetime of the first parameter shape @@ -629,8 +629,8 @@ returned. Here is how the new `select()` might look: # Rectangle(Point, Size) // upper-left, dimensions # } # fn compute_area(shape: &Shape) -> float { 0f } -fn select(shape: &tmp/Shape, threshold: float, - a: &r/T, b: &r/T) -> &r/T { +fn select(shape: &'tmp Shape, threshold: float, + a: &'r T, b: &'r T) -> &'r T { if compute_area(shape) > threshold {a} else {b} } ~~~ @@ -649,7 +649,7 @@ concise to just omit the named lifetime for `shape` altogether: # } # fn compute_area(shape: &Shape) -> float { 0f } fn select(shape: &Shape, threshold: float, - a: &r/T, b: &r/T) -> &r/T { + a: &'r T, b: &'r T) -> &'r T { if compute_area(shape) > threshold {a} else {b} } ~~~ diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index da247c648fc8c..cfd1b8dfef000 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use cast::transmute; use option; use prelude::*; @@ -15,11 +16,21 @@ use prelude::*; /// /// Similar to a mutable option type, but friendlier. -#[deriving_eq] pub struct Cell { mut value: Option } +impl cmp::Eq for Cell { + pure fn eq(&self, other: &Cell) -> bool { + unsafe { + let frozen_self: &Option = transmute(&mut self.value); + let frozen_other: &Option = transmute(&mut other.value); + frozen_self == frozen_other + } + } + pure fn ne(&self, other: &Cell) -> bool { !self.eq(other) } +} + /// Creates a new full cell with the given value. pub fn Cell(value: T) -> Cell { Cell { value: Some(value) } diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index 5b189abf4a373..12dc2d7e34158 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use cast; use either::{Either, Left, Right}; use kinds::Owned; use option; use option::{Option, Some, None, unwrap}; +use uint; use unstable; use vec; @@ -283,8 +285,12 @@ impl Peekable for PortSet { pure fn port_set_peek(self: &PortSet) -> bool { // It'd be nice to use self.port.each, but that version isn't // pure. - for vec::each(self.ports) |p| { - if p.peek() { return true } + for uint::range(0, vec::uniq_len(&const self.ports)) |i| { + // XXX: Botch pending demuting. + unsafe { + let port: &Port = cast::transmute(&mut self.ports[i]); + if port.peek() { return true } + } } false } diff --git a/src/libcore/container.rs b/src/libcore/container.rs index efcf1e26534c2..5044b3a6c5de1 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -14,10 +14,10 @@ use option::Option; pub trait Container { /// Return the number of elements in the container - pure fn len(&self) -> uint; + pure fn len(&const self) -> uint; /// Return true if the container contains no elements - pure fn is_empty(&self) -> bool; + pure fn is_empty(&const self) -> bool; } pub trait Mutable: Container { diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 20d207e9302b5..68a55792077e9 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -290,10 +290,10 @@ pub mod linear { impl Container for LinearMap { /// Return the number of elements in the map - pure fn len(&self) -> uint { self.size } + pure fn len(&const self) -> uint { self.size } /// Return true if the map contains no elements - pure fn is_empty(&self) -> bool { self.len() == 0 } + pure fn is_empty(&const self) -> bool { self.len() == 0 } } impl Mutable for LinearMap { @@ -555,10 +555,10 @@ pub mod linear { impl Container for LinearSet { /// Return the number of elements in the set - pure fn len(&self) -> uint { self.map.len() } + pure fn len(&const self) -> uint { self.map.len() } /// Return true if the set contains no elements - pure fn is_empty(&self) -> bool { self.map.is_empty() } + pure fn is_empty(&const self) -> bool { self.map.is_empty() } } impl Mutable for LinearSet { diff --git a/src/libcore/io.rs b/src/libcore/io.rs index b580d9c84a85c..50e7a42b7b17c 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -1116,7 +1116,7 @@ pub struct BytesWriter { impl Writer for BytesWriter { fn write(&self, v: &[const u8]) { let v_len = v.len(); - let bytes_len = self.bytes.len(); + let bytes_len = vec::uniq_len(&const self.bytes); let count = uint::max(bytes_len, self.pos + v_len); vec::reserve(&mut self.bytes, count); @@ -1131,7 +1131,7 @@ impl Writer for BytesWriter { } fn seek(&self, offset: int, whence: SeekStyle) { let pos = self.pos; - let len = self.bytes.len(); + let len = vec::uniq_len(&const self.bytes); self.pos = seek_in_buf(offset, pos, len, whence); } fn tell(&self) -> uint { self.pos } diff --git a/src/libcore/mutable.rs b/src/libcore/mutable.rs index 875d378b6453f..d0aa6e050f53c 100644 --- a/src/libcore/mutable.rs +++ b/src/libcore/mutable.rs @@ -46,8 +46,7 @@ pub fn unwrap(m: Mut) -> T { pub impl Data { fn borrow_mut(&self, op: &fn(t: &mut T) -> R) -> R { match self.mode { - Immutable => fail!(fmt!("%? currently immutable", - self.value)), + Immutable => fail!(~"currently immutable"), ReadOnly | Mutable => {} } @@ -62,8 +61,7 @@ pub impl Data { fn borrow_imm(&self, op: &fn(t: &T) -> R) -> R { match self.mode { - Mutable => fail!(fmt!("%? currently mutable", - self.value)), + Mutable => fail!(~"currently mutable"), ReadOnly | Immutable => {} } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 237fc762b3c53..5e5396ea12114 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -228,14 +228,14 @@ pub pure fn while_some(x: Option, blk: &fn(v: T) -> Option) { } #[inline(always)] -pub pure fn is_none(opt: &Option) -> bool { +pub pure fn is_none(opt: &const Option) -> bool { //! Returns true if the option equals `none` match *opt { None => true, Some(_) => false } } #[inline(always)] -pub pure fn is_some(opt: &Option) -> bool { +pub pure fn is_some(opt: &const Option) -> bool { //! Returns true if the option contains some value !is_none(opt) @@ -333,11 +333,11 @@ impl MutableIter for Option { pub impl Option { /// Returns true if the option equals `none` #[inline(always)] - pure fn is_none(&self) -> bool { is_none(self) } + pure fn is_none(&const self) -> bool { is_none(self) } /// Returns true if the option contains some value #[inline(always)] - pure fn is_some(&self) -> bool { is_some(self) } + pure fn is_some(&const self) -> bool { is_some(self) } /** * Update an optional value by optionally running its content by reference diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 481a61f4ab71d..c1b6b26d86a35 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -223,8 +223,8 @@ pub unsafe fn array_each(arr: **T, cb: &fn(*T)) { } pub trait Ptr { - pure fn is_null(&self) -> bool; - pure fn is_not_null(&self) -> bool; + pure fn is_null(&const self) -> bool; + pure fn is_not_null(&const self) -> bool; pure fn offset(&self, count: uint) -> Self; } @@ -232,11 +232,11 @@ pub trait Ptr { impl Ptr for *T { /// Returns true if the pointer is equal to the null pointer. #[inline(always)] - pure fn is_null(&self) -> bool { is_null(*self) } + pure fn is_null(&const self) -> bool { is_null(*self) } /// Returns true if the pointer is not equal to the null pointer. #[inline(always)] - pure fn is_not_null(&self) -> bool { is_not_null(*self) } + pure fn is_not_null(&const self) -> bool { is_not_null(*self) } /// Calculates the offset from a pointer. #[inline(always)] @@ -247,11 +247,11 @@ impl Ptr for *T { impl Ptr for *mut T { /// Returns true if the pointer is equal to the null pointer. #[inline(always)] - pure fn is_null(&self) -> bool { is_null(*self) } + pure fn is_null(&const self) -> bool { is_null(*self) } /// Returns true if the pointer is not equal to the null pointer. #[inline(always)] - pure fn is_not_null(&self) -> bool { is_not_null(*self) } + pure fn is_not_null(&const self) -> bool { is_not_null(*self) } /// Calculates the offset from a mutable pointer. #[inline(always)] diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index e6a4a99df4419..83df9b7c00fc3 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -499,7 +499,7 @@ impl TyVisitor for ReprVisitor { } fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool { - match self.var_stk[self.var_stk.len() - 1] { + match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] { Degenerate | TagMatch => { if i != 0 { self.writer.write_str(", "); @@ -517,7 +517,7 @@ impl TyVisitor for ReprVisitor { _disr_val: int, n_fields: uint, _name: &str) -> bool { - match self.var_stk[self.var_stk.len() - 1] { + match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] { Degenerate | TagMatch => { if n_fields > 0 { self.writer.write_char(')'); diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 0fd373b803fb5..40a6873ad6725 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -127,7 +127,7 @@ type TaskGroupInner = &'self mut Option; // A taskgroup is 'dead' when nothing can cause it to fail; only members can. pure fn taskgroup_is_dead(tg: &TaskGroupData) -> bool { - (&tg.members).is_empty() + (&const tg.members).is_empty() } // A list-like structure by which taskgroups keep track of all ancestor groups diff --git a/src/libcore/trie.rs b/src/libcore/trie.rs index 26532c1a4ff70..6b2f2bb6a7dbe 100644 --- a/src/libcore/trie.rs +++ b/src/libcore/trie.rs @@ -50,11 +50,11 @@ impl ReverseIter<(uint, &'self T)> for TrieMap { impl Container for TrieMap { /// Return the number of elements in the map #[inline(always)] - pure fn len(&self) -> uint { self.length } + pure fn len(&const self) -> uint { self.length } /// Return true if the map contains no elements #[inline(always)] - pure fn is_empty(&self) -> bool { self.len() == 0 } + pure fn is_empty(&const self) -> bool { self.len() == 0 } } impl Mutable for TrieMap { @@ -178,11 +178,11 @@ impl ReverseIter for TrieSet { impl Container for TrieSet { /// Return the number of elements in the set #[inline(always)] - pure fn len(&self) -> uint { self.map.len() } + pure fn len(&const self) -> uint { self.map.len() } /// Return true if the set contains no elements #[inline(always)] - pure fn is_empty(&self) -> bool { self.map.is_empty() } + pure fn is_empty(&const self) -> bool { self.map.is_empty() } } impl Mutable for TrieSet { diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 34d3c022dcac5..dc220eaed1bee 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -118,6 +118,14 @@ pub pure fn len(v: &[const T]) -> uint { as_const_buf(v, |_p, len| len) } +// A botch to tide us over until core and std are fully demuted. +pub pure fn uniq_len(v: &const ~[T]) -> uint { + unsafe { + let v: &~[T] = ::cast::transmute(v); + as_const_buf(*v, |_p, len| len) + } +} + /** * Creates and initializes an immutable vector. * @@ -1691,11 +1699,11 @@ pub mod traits { impl Container for &'self [const T] { /// Returns true if a vector contains no elements #[inline] - pure fn is_empty(&self) -> bool { is_empty(*self) } + pure fn is_empty(&const self) -> bool { is_empty(*self) } /// Returns the length of a vector #[inline] - pure fn len(&self) -> uint { len(*self) } + pure fn len(&const self) -> uint { len(*self) } } pub trait CopyableVector { @@ -1707,7 +1715,14 @@ impl CopyableVector for &'self [const T] { /// Returns a copy of the elements from [`start`..`end`) from `v`. #[inline] pure fn slice(&self, start: uint, end: uint) -> ~[T] { - slice(*self, start, end).to_vec() + // XXX: Purity workaround for stage0. + unsafe { + let mut result = ~[]; + for uint::range(start, end) |i| { + result.push(copy self[i]); + } + result + } } } @@ -2484,7 +2499,7 @@ impl iter::CopyableNonstrictIter for &'self [A] { impl iter::CopyableNonstrictIter for ~[A] { pure fn each_val(&const self, f: &fn(A) -> bool) { let mut i = 0; - while i < self.len() { + while i < uniq_len(self) { if !f(copy self[i]) { break; } i += 1; } diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index ddbac4085a7d7..434d992f50197 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -142,7 +142,7 @@ fn fold_item(cx: @mut TestCtxt, &&i: @ast::item, fld: @fold::ast_fold) -> Option<@ast::item> { cx.path.push(i.ident); debug!("current path: %s", - ast_util::path_name_i(cx.path, cx.sess.parse_sess.interner)); + ast_util::path_name_i(copy cx.path, cx.sess.parse_sess.interner)); if is_test_fn(i) || is_bench_fn(i) { match i.node { @@ -162,7 +162,7 @@ fn fold_item(cx: @mut TestCtxt, &&i: @ast::item, fld: @fold::ast_fold) should_fail: should_fail(i) }; cx.testfns.push(test); - debug!("have %u test/bench functions", cx.testfns.len()); + // debug!("have %u test/bench functions", cx.testfns.len()); } } } diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index a9aa5491631aa..92de7f3f5e6c7 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -79,6 +79,8 @@ fn warn_if_multiple_versions(e: @mut Env, crate_cache: @mut ~[cache_entry]) { use core::either::*; + let crate_cache = &mut *crate_cache; + if crate_cache.len() != 0u { let name = loader::crate_name_from_metas( *crate_cache[crate_cache.len() - 1].metas diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 0909a4437369d..ee52b48bc328b 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -96,6 +96,7 @@ pub fn iter_crate_data(cstore: @mut CStore, } pub fn add_used_crate_file(cstore: @mut CStore, lib: &Path) { + let cstore = &mut *cstore; if !vec::contains(cstore.used_crate_files, lib) { cstore.used_crate_files.push(copy *lib); } @@ -108,6 +109,7 @@ pub fn get_used_crate_files(cstore: @mut CStore) -> ~[Path] { pub fn add_used_library(cstore: @mut CStore, lib: @~str) -> bool { fail_unless!(*lib != ~""); + let cstore = &mut *cstore; if cstore.used_libraries.contains(&*lib) { return false; } cstore.used_libraries.push(/*bad*/ copy *lib); true diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 89700427d9674..17bdf318e0708 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -271,6 +271,7 @@ pub impl CheckLoanCtxt { None => return, Some(loans) => loans }; + let new_loans: &mut ~[Loan] = new_loans; debug!("new_loans has length %?", new_loans.len()); diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index 2893c460fe262..e5f056619cc7e 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -129,9 +129,12 @@ fn req_loans_in_expr(ex: @ast::expr, ex.id, pprust::expr_to_str(ex, tcx.sess.intr())); // If this expression is borrowed, have to ensure it remains valid: - if !self.ignore_adjustments.contains(&ex.id) { - for tcx.adjustments.find(&ex.id).each |adjustments| { - self.guarantee_adjustments(ex, *adjustments); + { + let mut this = &mut *self; + if !this.ignore_adjustments.contains(&ex.id) { + for tcx.adjustments.find(&ex.id).each |adjustments| { + this.guarantee_adjustments(ex, *adjustments); + } } } @@ -288,9 +291,9 @@ fn req_loans_in_expr(ex: @ast::expr, } pub impl GatherLoanCtxt { - fn tcx(@mut self) -> ty::ctxt { self.bccx.tcx } + fn tcx(&mut self) -> ty::ctxt { self.bccx.tcx } - fn guarantee_adjustments(@mut self, + fn guarantee_adjustments(&mut self, expr: @ast::expr, adjustment: &ty::AutoAdjustment) { debug!("guarantee_adjustments(expr=%s, adjustment=%?)", @@ -348,7 +351,7 @@ pub impl GatherLoanCtxt { // out loans, which will be added to the `req_loan_map`. This can // also entail "rooting" GC'd pointers, which means ensuring // dynamically that they are not freed. - fn guarantee_valid(@mut self, + fn guarantee_valid(&mut self, cmt: cmt, req_mutbl: ast::mutability, scope_r: ty::Region) @@ -465,7 +468,7 @@ pub impl GatherLoanCtxt { // has type `@mut{f:int}`, this check might fail because `&x.f` // reqires an immutable pointer, but `f` lives in (aliased) // mutable memory. - fn check_mutbl(@mut self, + fn check_mutbl(&mut self, loan_kind: LoanKind, cmt: cmt) -> bckres { @@ -498,7 +501,7 @@ pub impl GatherLoanCtxt { } } - fn add_loans(@mut self, + fn add_loans(&mut self, cmt: cmt, loan_kind: LoanKind, scope_r: ty::Region, @@ -563,7 +566,7 @@ pub impl GatherLoanCtxt { } } - fn add_loans_to_scope_id(@mut self, + fn add_loans_to_scope_id(&mut self, scope_id: ast::node_id, +loans: ~[Loan]) { debug!("adding %u loans to scope_id %?: %s", diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 2afe9564b207d..a8af6a18c0057 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -849,21 +849,24 @@ pub impl Liveness { _ => self.tcx.sess.span_bug(sp, ~"Label on break/loop \ doesn't refer to a loop") }, - None => + None => { // Vanilla 'break' or 'loop', so use the enclosing // loop scope - if self.loop_scope.len() == 0 { + let loop_scope = &mut *self.loop_scope; + if loop_scope.len() == 0 { self.tcx.sess.span_bug(sp, ~"break outside loop"); } else { // FIXME(#5275): this shouldn't have to be a method... self.last_loop_scope() } + } } } fn last_loop_scope(&self) -> node_id { - *self.loop_scope.last() + let loop_scope = &mut *self.loop_scope; + *loop_scope.last() } fn ln_str(&self, ln: LiveNode) -> ~str { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 05a697194c8b5..6dcf1ba812863 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -818,18 +818,21 @@ pub fn determine_rp_in_crate(sess: Session, // C). For each dependent item D, we combine the variance of C // with the ambient variance where the reference occurred and then // update the region-parameterization of D to reflect the result. - while cx.worklist.len() != 0 { - let c_id = cx.worklist.pop(); - let c_variance = cx.region_paramd_items.get(&c_id); - debug!("popped %d from worklist", c_id); - match cx.dep_map.find(&c_id) { - None => {} - Some(deps) => { - for deps.each |dep| { - let v = add_variance(dep.ambient_variance, c_variance); - cx.add_rp(dep.id, v); + { + let cx = &mut *cx; + while cx.worklist.len() != 0 { + let c_id = cx.worklist.pop(); + let c_variance = cx.region_paramd_items.get(&c_id); + debug!("popped %d from worklist", c_id); + match cx.dep_map.find(&c_id) { + None => {} + Some(deps) => { + for deps.each |dep| { + let v = add_variance(dep.ambient_variance, c_variance); + cx.add_rp(dep.id, v); + } + } } - } } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 8127f88f25022..6561da0862ae5 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -457,7 +457,7 @@ pub struct Module { kind: ModuleKind, children: @HashMap, - imports: ~[@ImportDirective], + imports: @mut ~[@ImportDirective], // The anonymous children of this node. Anonymous children are pseudo- // modules that are implicitly created around items contained within @@ -495,7 +495,7 @@ pub fn Module(parent_link: ParentLink, def_id: def_id, kind: kind, children: @HashMap(), - imports: ~[], + imports: @mut ~[], anonymous_children: @HashMap(), import_resolutions: @HashMap(), glob_count: 0, @@ -505,7 +505,8 @@ pub fn Module(parent_link: ParentLink, pub impl Module { fn all_imports_resolved(&self) -> bool { - return self.imports.len() == self.resolved_import_count; + let imports = &mut *self.imports; + return imports.len() == self.resolved_import_count; } } @@ -647,6 +648,7 @@ pub impl NameBindings { None => { match (*type_def).module_def { Some(module_def) => { + let module_def = &mut *module_def; module_def.def_id.map(|def_id| def_mod(*def_id)) } @@ -1978,10 +1980,11 @@ pub impl Resolver { return; } - let import_count = module.imports.len(); + let imports = &mut *module.imports; + let import_count = imports.len(); while module.resolved_import_count < import_count { let import_index = module.resolved_import_count; - let import_directive = module.imports[import_index]; + let import_directive = imports[import_index]; match self.resolve_import_for_module(module, import_directive) { Failed => { // We presumably emitted an error. Continue. @@ -2288,7 +2291,8 @@ pub impl Resolver { (None, None) => { return Failed; } // If it's private, it's also unresolved. (Some(t), None) | (None, Some(t)) => { - match t.bindings.type_def { + let bindings = &mut *t.bindings; + match bindings.type_def { Some(ref type_def) => { if type_def.privacy == Private { return Failed; @@ -2296,7 +2300,7 @@ pub impl Resolver { } _ => () } - match t.bindings.value_def { + match bindings.value_def { Some(ref value_def) => { if value_def.privacy == Private { return Failed; @@ -2483,7 +2487,7 @@ pub impl Resolver { debug!("(resolving glob import) writing module resolution \ %? into `%s`", - is_none(&target_import_resolution.type_target), + is_none(&mut target_import_resolution.type_target), self.module_to_str(module_)); // Here we merge two import resolutions. @@ -2551,7 +2555,7 @@ pub impl Resolver { *self.session.str_of(ident), self.module_to_str(containing_module), self.module_to_str(module_), - dest_import_resolution.privacy); + copy dest_import_resolution.privacy); // Merge the child item into the import resolution. if (*name_bindings).defined_in_public_namespace(ValueNS) { @@ -2864,7 +2868,8 @@ pub impl Resolver { module_, name, TypeNS, DontSearchThroughModules); match resolve_result { Success(target) => { - match target.bindings.type_def { + let bindings = &mut *target.bindings; + match bindings.type_def { Some(ref type_def) => { match (*type_def).module_def { None => { @@ -3061,10 +3066,10 @@ pub impl Resolver { fn report_unresolved_imports(@mut self, module_: @mut Module) { let index = module_.resolved_import_count; - let import_count = module_.imports.len(); + let imports: &mut ~[@ImportDirective] = &mut *module_.imports; + let import_count = imports.len(); if index != import_count { - self.session.span_err(module_.imports[index].span, - ~"unresolved import"); + self.session.span_err(imports[index].span, ~"unresolved import"); } // Descend into children and anonymous children. @@ -4253,10 +4258,10 @@ pub impl Resolver { match bindings_list { Some(bindings_list) - if !bindings_list.contains_key(&ident) - => { - let last_rib = self.value_ribs[ - self.value_ribs.len() - 1]; + if !bindings_list.contains_key(&ident) => { + let this = &mut *self; + let last_rib = this.value_ribs[ + this.value_ribs.len() - 1]; last_rib.bindings.insert(ident, dl_def(def)); bindings_list.insert(ident, pat_id); @@ -4275,8 +4280,9 @@ pub impl Resolver { // Not bound in the same pattern: do nothing } None => { - let last_rib = self.value_ribs[ - self.value_ribs.len() - 1]; + let this = &mut *self; + let last_rib = this.value_ribs[ + this.value_ribs.len() - 1]; last_rib.bindings.insert(ident, dl_def(def)); } @@ -4723,14 +4729,16 @@ pub impl Resolver { } fn find_best_match_for_name(@mut self, name: &str) -> Option<~str> { + let this = &mut *self; + let mut maybes: ~[~str] = ~[]; let mut values: ~[uint] = ~[]; - let mut j = self.value_ribs.len(); + let mut j = this.value_ribs.len(); while j != 0 { j -= 1; - for self.value_ribs[j].bindings.each_entry |e| { - vec::push(&mut maybes, copy *self.session.str_of(e.key)); + for this.value_ribs[j].bindings.each_entry |e| { + vec::push(&mut maybes, copy *this.session.str_of(e.key)); vec::push(&mut values, uint::max_value); } } @@ -4758,12 +4766,14 @@ pub impl Resolver { } fn name_exists_in_scope_struct(@mut self, name: &str) -> bool { - let mut i = self.type_ribs.len(); + let this = &mut *self; + + let mut i = this.type_ribs.len(); while i != 0 { i -= 1; - match self.type_ribs[i].kind { + match this.type_ribs[i].kind { MethodRibKind(node_id, _) => - for self.crate.node.module.items.each |item| { + for this.crate.node.module.items.each |item| { if item.id == node_id { match item.node { item_struct(class_def, _) => { @@ -4771,7 +4781,7 @@ pub impl Resolver { match field.node.kind { unnamed_field => {}, named_field(ident, _, _) => { - if str::eq_slice(*self.session.str_of(ident), + if str::eq_slice(*this.session.str_of(ident), name) { return true } @@ -4877,8 +4887,9 @@ pub impl Resolver { expr_loop(_, Some(label)) => { do self.with_label_rib { + let this = &mut *self; let def_like = dl_def(def_label(expr.id)); - let rib = self.label_ribs[self.label_ribs.len() - 1]; + let rib = this.label_ribs[this.label_ribs.len() - 1]; rib.bindings.insert(label, def_like); visit_expr(expr, (), visitor); @@ -5144,21 +5155,21 @@ pub impl Resolver { // be sure that there is only one main function // fn check_duplicate_main(@mut self) { - if self.attr_main_fn.is_none() { - if self.main_fns.len() >= 1u { + let this = &mut *self; + if this.attr_main_fn.is_none() { + if this.main_fns.len() >= 1u { let mut i = 1u; - while i < self.main_fns.len() { - let (_, dup_main_span) = - option::unwrap(self.main_fns[i]); - self.session.span_err( + while i < this.main_fns.len() { + let (_, dup_main_span) = option::unwrap(this.main_fns[i]); + this.session.span_err( dup_main_span, ~"multiple 'main' functions"); i += 1; } - *self.session.main_fn = self.main_fns[0]; + *this.session.main_fn = this.main_fns[0]; } } else { - *self.session.main_fn = self.attr_main_fn; + *this.session.main_fn = this.attr_main_fn; } } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index a340e6472b8f7..4836ce062c9ca 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -854,7 +854,9 @@ pub fn need_invoke(bcx: block) -> bool { // Walk the scopes to look for cleanups let mut cur = bcx; loop { - match *cur.kind { + let current = &mut *cur; + let kind = &mut *current.kind; + match *kind { block_scope(ref mut inf) => { for vec::each((*inf).cleanups) |cleanup| { match *cleanup { @@ -868,7 +870,7 @@ pub fn need_invoke(bcx: block) -> bool { } _ => () } - cur = match cur.parent { + cur = match current.parent { Some(next) => next, None => return false } diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 1d31dc4fb8acf..96c124d60de9f 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -50,7 +50,7 @@ pub fn count_insn(cx: block, category: &str) { if cx.ccx().sess.count_llvm_insns() { let h = cx.ccx().stats.llvm_insns; - let v = cx.ccx().stats.llvm_insn_ctxt; + let v = &*cx.ccx().stats.llvm_insn_ctxt; // Build version of path with cycles removed. diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 40394391f1adb..616a5f994992b 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -186,12 +186,14 @@ pub fn trans_log(log_ex: @ast::expr, return expr::trans_into(bcx, lvl, expr::Ignore); } - let modpath = vec::append( - ~[path_mod(ccx.sess.ident_of(ccx.link_meta.name.to_owned()))], - bcx.fcx.path.filtered(|e| - match *e { path_mod(_) => true, _ => false } - )); - let modname = path_str(ccx.sess, modpath); + let (modpath, modname) = { + let path = &mut bcx.fcx.path; + let modpath = vec::append( + ~[path_mod(ccx.sess.ident_of(ccx.link_meta.name.to_owned()))], + path.filtered(|e| match *e { path_mod(_) => true, _ => false })); + let modname = path_str(ccx.sess, modpath); + (modpath, modname) + }; let global = if ccx.module_data.contains_key(&modname) { ccx.module_data.get(&modname) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 4a1837fd9d0e7..e4b9d01c50982 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -845,7 +845,8 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata { let dbg_cx = (/*bad*/copy cx.dbg_cx).get(); debug!("~~"); - debug!("%?", fcx.id); + + let fcx = &mut *fcx; let sp = fcx.span.get(); debug!("%s", cx.sess.codemap.span_to_str(sp)); diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 8302f46120e66..284a5eac39db8 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -234,18 +234,21 @@ pub fn lazily_emit_simplified_tydesc_glue(ccx: @CrateContext, if simpl != ti.ty { let simpl_ti = get_tydesc(ccx, simpl); lazily_emit_tydesc_glue(ccx, field, simpl_ti); - if field == abi::tydesc_field_take_glue { - ti.take_glue = - simpl_ti.take_glue.map(|v| cast_glue(ccx, ti, *v)); - } else if field == abi::tydesc_field_drop_glue { - ti.drop_glue = - simpl_ti.drop_glue.map(|v| cast_glue(ccx, ti, *v)); - } else if field == abi::tydesc_field_free_glue { - ti.free_glue = - simpl_ti.free_glue.map(|v| cast_glue(ccx, ti, *v)); - } else if field == abi::tydesc_field_visit_glue { - ti.visit_glue = - simpl_ti.visit_glue.map(|v| cast_glue(ccx, ti, *v)); + { + let simpl_ti = &mut *simpl_ti; + if field == abi::tydesc_field_take_glue { + ti.take_glue = + simpl_ti.take_glue.map(|v| cast_glue(ccx, ti, *v)); + } else if field == abi::tydesc_field_drop_glue { + ti.drop_glue = + simpl_ti.drop_glue.map(|v| cast_glue(ccx, ti, *v)); + } else if field == abi::tydesc_field_free_glue { + ti.free_glue = + simpl_ti.free_glue.map(|v| cast_glue(ccx, ti, *v)); + } else if field == abi::tydesc_field_visit_glue { + ti.visit_glue = + simpl_ti.visit_glue.map(|v| cast_glue(ccx, ti, *v)); + } } return true; } diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 692dc392173b3..593919d108b87 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -185,7 +185,11 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) pub fn type_needs(cx: Context, use_: uint, ty: ty::t) { // Optimization -- don't descend type if all params already have this use - for uint::range(0, cx.uses.len()) |i| { + let len = { + let uses = &*cx.uses; + uses.len() + }; + for uint::range(0, len) |i| { if cx.uses[i] & use_ != use_ { type_needs_inner(cx, use_, ty, @Nil); return; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fcebcaf501ee1..599fa28e24224 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2184,7 +2184,7 @@ pub fn type_moves_by_default(cx: ctxt, ty: t) -> bool { // True if instantiating an instance of `r_ty` requires an instance of `r_ty`. pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool { - fn type_requires(cx: ctxt, seen: @mut ~[def_id], + fn type_requires(cx: ctxt, seen: &mut ~[def_id], r_ty: t, ty: t) -> bool { debug!("type_requires(%s, %s)?", ::util::ppaux::ty_to_str(cx, r_ty), @@ -2202,7 +2202,7 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool { return r; } - fn subtypes_require(cx: ctxt, seen: @mut ~[def_id], + fn subtypes_require(cx: ctxt, seen: &mut ~[def_id], r_ty: t, ty: t) -> bool { debug!("subtypes_require(%s, %s)?", ::util::ppaux::ty_to_str(cx, r_ty), diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index f3fff416c5591..752d9107d822a 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1696,7 +1696,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(expr.id, fty); let inherited_purity = - ty::determine_inherited_purity(fcx.purity, purity, + ty::determine_inherited_purity(copy fcx.purity, purity, fn_ty.sigil); // We inherit the same self info as the enclosing scope, diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 48a37c9e72ad0..6e86bbca0d1c3 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -10,6 +10,7 @@ use core::prelude::*; +use middle::resolve::Impl; use middle::ty::{param_ty, substs}; use middle::ty; use middle::typeck::check::{FnCtxt, impl_self_ty}; @@ -240,6 +241,7 @@ pub fn lookup_vtable(vcx: &VtableContext, // Nothing found. Continue. } Some(implementations) => { + let implementations: &mut ~[@Impl] = implementations; // implementations is the list of all impls in scope for // trait_ty. (Usually, there's just one.) for uint::range(0, implementations.len()) |i| { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 3d2ed867de1f2..699b8ad74e4ce 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -466,14 +466,13 @@ pub impl CoherenceChecker { } } - fn iter_impls_of_trait(&self, trait_def_id: def_id, - f: &fn(@Impl)) { - + fn iter_impls_of_trait(&self, trait_def_id: def_id, f: &fn(@Impl)) { let coherence_info = &mut self.crate_context.coherence_info; let extension_methods = &coherence_info.extension_methods; match extension_methods.find(&trait_def_id) { Some(impls) => { + let impls: &mut ~[@Impl] = impls; for uint::range(0, impls.len()) |i| { f(impls[i]); } diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 03649faff63d6..11da6b60328ce 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -559,15 +559,16 @@ pub impl InferCtxt { } fn start_snapshot(@mut self) -> Snapshot { + let this = &mut *self; Snapshot { ty_var_bindings_len: - self.ty_var_bindings.bindings.len(), + this.ty_var_bindings.bindings.len(), int_var_bindings_len: - self.int_var_bindings.bindings.len(), + this.int_var_bindings.bindings.len(), float_var_bindings_len: - self.float_var_bindings.bindings.len(), + this.float_var_bindings.bindings.len(), region_vars_snapshot: - self.region_vars.start_snapshot(), + this.region_vars.start_snapshot(), } } diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index 9cf2d145eacb4..430a5eab64e0b 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -700,8 +700,8 @@ impl cmp::Eq for BitvSet { } impl Container for BitvSet { - pure fn len(&self) -> uint { self.size } - pure fn is_empty(&self) -> bool { self.size == 0 } + pure fn len(&const self) -> uint { self.size } + pure fn is_empty(&const self) -> bool { self.size == 0 } } impl Mutable for BitvSet { diff --git a/src/libstd/deque.rs b/src/libstd/deque.rs index 90269e28b8a42..86304f48e7929 100644 --- a/src/libstd/deque.rs +++ b/src/libstd/deque.rs @@ -23,10 +23,10 @@ pub struct Deque { impl Container for Deque { /// Return the number of elements in the deque - pure fn len(&self) -> uint { self.nelts } + pure fn len(&const self) -> uint { self.nelts } /// Return true if the deque contains no elements - pure fn is_empty(&self) -> bool { self.len() == 0 } + pure fn is_empty(&const self) -> bool { self.len() == 0 } } impl Mutable for Deque { diff --git a/src/libstd/flatpipes.rs b/src/libstd/flatpipes.rs index e2e09f1d6750a..c5515c63b29a2 100644 --- a/src/libstd/flatpipes.rs +++ b/src/libstd/flatpipes.rs @@ -569,12 +569,12 @@ pub mod bytepipes { impl BytePort for PipeBytePort { fn try_recv(&self, count: uint) -> Option<~[u8]> { - if self.buf.len() >= count { + if vec::uniq_len(&const self.buf) >= count { let mut bytes = ::core::util::replace(&mut self.buf, ~[]); self.buf = bytes.slice(count, bytes.len()); bytes.truncate(count); return Some(bytes); - } else if self.buf.len() > 0 { + } else if vec::uniq_len(&const self.buf) > 0 { let mut bytes = ::core::util::replace(&mut self.buf, ~[]); fail_unless!(count > bytes.len()); match self.try_recv(count - bytes.len()) { @@ -584,7 +584,7 @@ pub mod bytepipes { } None => return None } - } else if self.buf.is_empty() { + } else if vec::uniq_len(&const self.buf) == 0 { match self.port.try_recv() { Some(buf) => { fail_unless!(!buf.is_empty()); diff --git a/src/libstd/json.rs b/src/libstd/json.rs index e52d08c40fe33..f2f37604fb564 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -757,12 +757,16 @@ pub fn Decoder(json: Json) -> Decoder { priv impl Decoder/&self { fn peek(&self) -> &'self Json { - if self.stack.len() == 0 { self.stack.push(&self.json); } - self.stack[self.stack.len() - 1] + if vec::uniq_len(&const self.stack) == 0 { + self.stack.push(&self.json); + } + self.stack[vec::uniq_len(&const self.stack) - 1] } fn pop(&self) -> &'self Json { - if self.stack.len() == 0 { self.stack.push(&self.json); } + if vec::uniq_len(&const self.stack) == 0 { + self.stack.push(&self.json); + } self.stack.pop() } } diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 54fbae956ce5c..a93e94e0d0430 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -879,7 +879,8 @@ impl io::Reader for TcpSocketBuf { // If possible, copy up to `len` bytes from the internal // `data.buf` into `buf` - let nbuffered = self.data.buf.len() - self.data.buf_off; + let nbuffered = vec::uniq_len(&const self.data.buf) - + self.data.buf_off; let needed = len - count; if nbuffered > 0 { unsafe { @@ -931,7 +932,7 @@ impl io::Reader for TcpSocketBuf { } fn read_byte(&self) -> int { loop { - if self.data.buf.len() > self.data.buf_off { + if vec::uniq_len(&const self.data.buf) > self.data.buf_off { let c = self.data.buf[self.data.buf_off]; self.data.buf_off += 1; return c as int diff --git a/src/libstd/oldmap.rs b/src/libstd/oldmap.rs index a4b00e4dd0428..0a07a24e8ee5c 100644 --- a/src/libstd/oldmap.rs +++ b/src/libstd/oldmap.rs @@ -101,7 +101,7 @@ pub mod chained { } pure fn search_tbl(&self, k: &K, h: uint) -> SearchResult { - let idx = h % vec::len(self.chains); + let idx = h % vec::uniq_len(&const self.chains); match copy self.chains[idx] { None => { debug!("search_tbl: none, comp %u, hash %u, idx %u", @@ -121,7 +121,7 @@ pub mod chained { } fn rehash(@self) { - let n_old_chains = self.chains.len(); + let n_old_chains = vec::uniq_len(&const self.chains); let n_new_chains: uint = uint::next_power_of_two(n_old_chains+1u); let mut new_chains = chains(n_new_chains); for self.each_entry |entry| { @@ -137,7 +137,7 @@ pub mod chained { pure fn each_entry(&self, blk: &fn(@Entry) -> bool) { // n.b. we can't use vec::iter() here because self.chains // is stored in a mutable location. - let mut i = 0u, n = self.chains.len(); + let mut i = 0u, n = vec::uniq_len(&const self.chains); while i < n { let mut chain = self.chains[i]; loop { @@ -161,8 +161,8 @@ pub mod chained { } impl Container for HashMap_ { - pure fn len(&self) -> uint { self.count } - pure fn is_empty(&self) -> bool { self.count == 0 } + pure fn len(&const self) -> uint { self.count } + pure fn is_empty(&const self) -> bool { self.count == 0 } } pub impl HashMap_ { @@ -179,7 +179,7 @@ pub mod chained { match self.search_tbl(&k, hash) { NotFound => { self.count += 1u; - let idx = hash % vec::len(self.chains); + let idx = hash % vec::uniq_len(&const self.chains); let old_chain = self.chains[idx]; self.chains[idx] = Some(@Entry { hash: hash, @@ -188,7 +188,7 @@ pub mod chained { next: old_chain}); // consider rehashing if more 3/4 full - let nchains = vec::len(self.chains); + let nchains = vec::uniq_len(&const self.chains); let load = util::Rational { num: (self.count + 1u) as int, den: nchains as int, @@ -271,7 +271,7 @@ pub mod chained { match self.search_tbl(&key, hash) { NotFound => { self.count += 1u; - let idx = hash % vec::len(self.chains); + let idx = hash % vec::uniq_len(&const self.chains); let old_chain = self.chains[idx]; self.chains[idx] = Some(@Entry { hash: hash, @@ -280,7 +280,7 @@ pub mod chained { next: old_chain}); // consider rehashing if more 3/4 full - let nchains = vec::len(self.chains); + let nchains = vec::uniq_len(&const self.chains); let load = util::Rational { num: (self.count + 1u) as int, den: nchains as int, diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs index b9b5075c43498..a5a291c5b18f5 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libstd/priority_queue.rs @@ -37,10 +37,10 @@ impl BaseIter for PriorityQueue { impl Container for PriorityQueue { /// Returns the length of the queue - pure fn len(&self) -> uint { self.data.len() } + pure fn len(&const self) -> uint { vec::uniq_len(&const self.data) } /// Returns true if a queue contains no elements - pure fn is_empty(&self) -> bool { self.data.is_empty() } + pure fn is_empty(&const self) -> bool { self.len() == 0 } } impl Mutable for PriorityQueue { diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs index b1ef0233d97e2..f7e31bc7df758 100644 --- a/src/libstd/sha1.rs +++ b/src/libstd/sha1.rs @@ -91,7 +91,7 @@ pub fn sha1() -> @Sha1 { } fn process_msg_block(st: &mut Sha1State) { fail_unless!((vec::len(st.h) == digest_buf_len)); - fail_unless!((vec::len(*st.work_buf) == work_buf_len)); + fail_unless!((vec::uniq_len(st.work_buf) == work_buf_len)); let mut t: int; // Loop counter let mut w = st.work_buf; diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index c63ef9b72584b..dc2688a20e73d 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -50,18 +50,19 @@ impl ReverseIter<(uint, &'self V)> for SmallIntMap { impl Container for SmallIntMap { /// Return the number of elements in the map - pure fn len(&self) -> uint { + pure fn len(&const self) -> uint { let mut sz = 0; - for self.v.each |item| { - if item.is_some() { - sz += 1; + for uint::range(0, vec::uniq_len(&const self.v)) |i| { + match self.v[i] { + Some(_) => sz += 1, + None => {} } } sz } /// Return true if the map contains no elements - pure fn is_empty(&self) -> bool { self.len() == 0 } + pure fn is_empty(&const self) -> bool { self.len() == 0 } } impl Mutable for SmallIntMap { diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 43c68196eb826..40be303a14782 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -68,9 +68,14 @@ fn part(arr: &mut [T], left: uint, let mut storage_index: uint = left; let mut i: uint = left; while i < right { - if compare_func(&arr[i], &arr[right]) { - arr[i] <-> arr[storage_index]; - storage_index += 1; + // XXX: Unsafe because borrow check doesn't handle this right + unsafe { + let a: &T = cast::transmute(&mut arr[i]); + let b: &T = cast::transmute(&mut arr[right]); + if compare_func(a, b) { + arr[i] <-> arr[storage_index]; + storage_index += 1; + } } i += 1; } @@ -451,7 +456,10 @@ impl MergeState { base2: uint, len2: uint) { fail_unless!(len1 != 0 && len2 != 0 && base1+len1 == base2); - let mut tmp = vec::slice(array, base1, base1+len1).to_vec(); + let mut tmp = ~[]; + for uint::range(base1, base1+len1) |i| { + tmp.push(array[i]); + } let mut c1 = 0; let mut c2 = base2; @@ -554,7 +562,10 @@ impl MergeState { base2: uint, len2: uint) { fail_unless!(len1 != 1 && len2 != 0 && base1 + len1 == base2); - let mut tmp = vec::slice(array, base2, base2+len2).to_vec(); + let mut tmp = ~[]; + for uint::range(base2, base2+len2) |i| { + tmp.push(array[i]); + } let mut c1 = base1 + len1 - 1; let mut c2 = len2 - 1; @@ -702,7 +713,11 @@ fn copy_vec(dest: &mut [T], s1: uint, from: &[const T], s2: uint, len: uint) { fail_unless!(s1+len <= dest.len() && s2+len <= from.len()); - let slice = vec::slice(from, s2, s2+len).to_vec(); + let mut slice = ~[]; + for uint::range(s2, s2+len) |i| { + slice.push(from[i]); + } + for slice.eachi |i, v| { dest[s1+i] = *v; } @@ -721,7 +736,7 @@ mod test_qsort3 { quick_sort3::(v1); let mut i = 0; while i < len { - debug!(v2[i]); + // debug!(v2[i]); fail_unless!((v2[i] == v1[i])); i += 1; } @@ -768,7 +783,7 @@ mod test_qsort { quick_sort::(v1, leual); let mut i = 0u; while i < len { - debug!(v2[i]); + // debug!(v2[i]); fail_unless!((v2[i] == v1[i])); i += 1; } @@ -919,7 +934,7 @@ mod test_tim_sort { tim_sort::(v1); let mut i = 0u; while i < len { - debug!(v2[i]); + // debug!(v2[i]); fail_unless!((v2[i] == v1[i])); i += 1u; } diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 63cf4c998df7f..fcc60c8d97819 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -358,7 +358,11 @@ pub fn run_tests_console(opts: &TestOpts, fn print_failures(st: @ConsoleTestState) { st.out.write_line(~"\nfailures:"); - let mut failures = st.failures.map(|t| t.name.to_str()); + let mut failures = ~[]; + for uint::range(0, vec::uniq_len(&const st.failures)) |i| { + let name = copy st.failures[i].name; + failures.push(name.to_str()); + } sort::tim_sort(failures); for vec::each(failures) |name| { st.out.write_line(fmt!(" %s", name.to_str())); diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 7192da7b88e1f..f4d58568ae7d6 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -106,10 +106,10 @@ impl<'self, K: TotalOrd, V> impl Container for TreeMap { /// Return the number of elements in the map - pure fn len(&self) -> uint { self.length } + pure fn len(&const self) -> uint { self.length } /// Return true if the map contains no elements - pure fn is_empty(&self) -> bool { self.root.is_none() } + pure fn is_empty(&const self) -> bool { self.root.is_none() } } impl Mutable for TreeMap { @@ -276,11 +276,11 @@ impl Ord for TreeSet { impl Container for TreeSet { /// Return the number of elements in the set #[inline(always)] - pure fn len(&self) -> uint { self.map.len() } + pure fn len(&const self) -> uint { self.map.len() } /// Return true if the set contains no elements #[inline(always)] - pure fn is_empty(&self) -> bool { self.map.is_empty() } + pure fn is_empty(&const self) -> bool { self.map.is_empty() } } impl Mutable for TreeSet { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 97719a140a6a5..538f0de8c842b 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -252,8 +252,8 @@ pub impl FileMap { // about what ends a line between this file and parse.rs fn next_line(&self, +pos: BytePos) { // the new charpos must be > the last one (or it's the first one). - fail_unless!((self.lines.len() == 0) - || (self.lines[self.lines.len() - 1] < pos)); + let lines = &mut *self.lines; + fail_unless!((lines.len() == 0) || (lines[lines.len() - 1] < pos)); self.lines.push(pos); } @@ -302,11 +302,12 @@ pub impl CodeMap { +substr: FileSubstr, src: @~str ) -> @FileMap { - let start_pos = if self.files.len() == 0 { + let files = &mut *self.files; + let start_pos = if files.len() == 0 { 0 } else { - let last_start = self.files.last().start_pos.to_uint(); - let last_len = self.files.last().src.len(); + let last_start = files.last().start_pos.to_uint(); + let last_len = files.last().src.len(); last_start + last_len }; @@ -364,7 +365,8 @@ pub impl CodeMap { } pub fn span_to_str(&self, sp: span) -> ~str { - if self.files.len() == 0 && sp == dummy_sp() { + let files = &mut *self.files; + if files.len() == 0 && sp == dummy_sp() { return ~"no-location"; } @@ -409,7 +411,8 @@ pub impl CodeMap { priv impl CodeMap { fn lookup_filemap_idx(&self, +pos: BytePos) -> uint { - let len = self.files.len(); + let files = &*self.files; + let len = files.len(); let mut a = 0u; let mut b = len; while b - a > 1u { @@ -433,10 +436,11 @@ priv impl CodeMap { let idx = self.lookup_filemap_idx(pos); let f = self.files[idx]; let mut a = 0u; - let mut b = f.lines.len(); + let lines = &*f.lines; + let mut b = lines.len(); while b - a > 1u { let m = (a + b) / 2u; - if f.lines[m] > pos { b = m; } else { a = m; } + if lines[m] > pos { b = m; } else { a = m; } } return FileMapAndLine {fm: f, line: a}; } diff --git a/src/libsyntax/ext/deriving.rs b/src/libsyntax/ext/deriving.rs index 54b123bff2ff9..76ab21f403b3f 100644 --- a/src/libsyntax/ext/deriving.rs +++ b/src/libsyntax/ext/deriving.rs @@ -226,7 +226,7 @@ fn create_eq_method(cx: @ext_ctxt, attrs: ~[], generics: ast_util::empty_generics(), self_ty: self_ty, - purity: pure_fn, + purity: impure_fn, decl: fn_decl, body: body_block, id: cx.next_id(), @@ -405,7 +405,7 @@ fn create_iter_bytes_method(cx: @ext_ctxt, attrs: ~[], generics: ast_util::empty_generics(), self_ty: self_ty, - purity: pure_fn, + purity: impure_fn, decl: fn_decl, body: body_block, id: cx.next_id(), diff --git a/src/libsyntax/ext/pipes/check.rs b/src/libsyntax/ext/pipes/check.rs index 30e7e832db197..29c9e86ec626a 100644 --- a/src/libsyntax/ext/pipes/check.rs +++ b/src/libsyntax/ext/pipes/check.rs @@ -41,7 +41,8 @@ impl proto::visitor<(), (), ()> for @ext_ctxt { fn visit_proto(&self, _proto: protocol, _states: &[()]) { } fn visit_state(&self, state: state, _m: &[()]) { - if state.messages.len() == 0 { + let messages = &*state.messages; + if messages.len() == 0 { self.span_warn( state.span, // use a real span! fmt!("state %s contains no messages, \ diff --git a/src/libsyntax/ext/pipes/liveness.rs b/src/libsyntax/ext/pipes/liveness.rs index 15ba7f95538fa..c6fdf4d9c1b21 100644 --- a/src/libsyntax/ext/pipes/liveness.rs +++ b/src/libsyntax/ext/pipes/liveness.rs @@ -91,7 +91,7 @@ pub fn analyze(proto: protocol, _cx: @ext_ctxt) { let states = str::connect(self_live.map(|s| copy s.name), ~" "); debug!("protocol %s is unbounded due to loops involving: %s", - proto.name, states); + copy proto.name, states); // Someday this will be configurable with a warning //cx.span_warn(empty_span(), @@ -103,7 +103,7 @@ pub fn analyze(proto: protocol, _cx: @ext_ctxt) { proto.bounded = Some(false); } else { - debug!("protocol %s is bounded. yay!", proto.name); + debug!("protocol %s is bounded. yay!", copy proto.name); proto.bounded = Some(true); } } diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index c9680ac02c90e..a47b39a45c864 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -156,7 +156,10 @@ pub impl protocol_ { ~"proto://" + self.name } - fn num_states(&mut self) -> uint { self.states.len() } + fn num_states(&mut self) -> uint { + let states = &mut *self.states; + states.len() + } fn has_ty_params(&mut self) -> bool { for self.states.each |s| { @@ -180,9 +183,10 @@ pub impl protocol_ { +generics: ast::Generics) -> state { let messages = @mut ~[]; + let states = &*self.states; let state = @state_ { - id: self.states.len(), + id: states.len(), name: name, ident: ident, span: self.span, diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 908fbd4482510..0196ee6d18426 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -106,8 +106,9 @@ pub pure fn dup_tt_reader(r: @mut TtReader) -> @mut TtReader { } -pure fn lookup_cur_matched_by_matched(r: @mut TtReader, - start: @named_match) -> @named_match { +pure fn lookup_cur_matched_by_matched(r: &mut TtReader, + start: @named_match) + -> @named_match { pure fn red(+ad: @named_match, idx: &uint) -> @named_match { match *ad { matched_nonterminal(_) => { @@ -117,18 +118,20 @@ pure fn lookup_cur_matched_by_matched(r: @mut TtReader, matched_seq(ref ads, _) => ads[*idx] } } - vec::foldl(start, r.repeat_idx, red) + let r = &mut *r; + let repeat_idx = &r.repeat_idx; + vec::foldl(start, *repeat_idx, red) } -fn lookup_cur_matched(r: @mut TtReader, name: ident) -> @named_match { +fn lookup_cur_matched(r: &mut TtReader, name: ident) -> @named_match { lookup_cur_matched_by_matched(r, r.interpolations.get(&name)) } enum lis { lis_unconstrained, lis_constraint(uint, ident), lis_contradiction(~str) } -fn lockstep_iter_size(t: token_tree, r: @mut TtReader) -> lis { - fn lis_merge(lhs: lis, rhs: lis, r: @mut TtReader) -> lis { +fn lockstep_iter_size(t: token_tree, r: &mut TtReader) -> lis { + fn lis_merge(lhs: lis, rhs: lis, r: &mut TtReader) -> lis { match lhs { lis_unconstrained => copy rhs, lis_contradiction(_) => copy lhs, @@ -148,8 +151,10 @@ fn lockstep_iter_size(t: token_tree, r: @mut TtReader) -> lis { } match t { tt_delim(ref tts) | tt_seq(_, ref tts, _, _) => { - vec::foldl(lis_unconstrained, (*tts), |lis, tt| - lis_merge(lis, lockstep_iter_size(*tt, r), r)) + vec::foldl(lis_unconstrained, (*tts), |lis, tt| { + let lis2 = lockstep_iter_size(*tt, r); + lis_merge(lis, lis2, r) + }) } tt_tok(*) => lis_unconstrained, tt_nonterminal(_, name) => match *lookup_cur_matched(r, name) { @@ -160,12 +165,20 @@ fn lockstep_iter_size(t: token_tree, r: @mut TtReader) -> lis { } -pub fn tt_next_token(r: @mut TtReader) -> TokenAndSpan { +pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { let ret_val = TokenAndSpan { tok: copy r.cur_tok, sp: r.cur_span, }; - while r.cur.idx >= r.cur.readme.len() { + loop { + { + let cur = &mut *r.cur; + let readme = &mut *cur.readme; + if cur.idx < readme.len() { + break; + } + } + /* done with this set; pop or repeat? */ if ! r.cur.dotdotdoted || { *r.repeat_idx.last() == *r.repeat_len.last() - 1 } { diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 09ffd79c246e3..90f51fe9b65af 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -811,7 +811,7 @@ pub mod test { sp:span {lo:BytePos(21),hi:BytePos(23),expn_info: None}}; check_equal (tok1,tok2); // the 'main' id is already read: - check_equal (string_reader.last_pos,BytePos(28)); + check_equal (copy string_reader.last_pos,BytePos(28)); // read another token: let tok3 = string_reader.next_token(); let tok4 = TokenAndSpan{ @@ -819,7 +819,7 @@ pub mod test { sp:span {lo:BytePos(24),hi:BytePos(28),expn_info: None}}; check_equal (tok3,tok4); // the lparen is already read: - check_equal (string_reader.last_pos,BytePos(29)) + check_equal (copy string_reader.last_pos,BytePos(29)) } // check that the given reader produces the desired stream diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2ea304a0a9bc5..8a883b73a64a3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -412,7 +412,8 @@ pub impl Parser { fn parse_purity(&self) -> purity { if self.eat_keyword(&~"pure") { - return pure_fn; + // NB: We parse this as impure for bootstrapping purposes. + return impure_fn; } else if self.eat_keyword(&~"unsafe") { return unsafe_fn; } else { @@ -2668,7 +2669,8 @@ pub impl Parser { fn parse_optional_purity(&self) -> ast::purity { if self.eat_keyword(&~"pure") { - ast::pure_fn + // NB: We parse this as impure for bootstrapping purposes. + ast::impure_fn } else if self.eat_keyword(&~"unsafe") { ast::unsafe_fn } else { @@ -3418,7 +3420,8 @@ pub impl Parser { let prefix = Path(self.sess.cm.span_to_filename(*self.span)); let prefix = prefix.dir_path(); - let mod_path = Path(".").push_many(*self.mod_path_stack); + let mod_path_stack = &*self.mod_path_stack; + let mod_path = Path(".").push_many(*mod_path_stack); let default_path = *self.sess.interner.get(id) + ~".rs"; let file_path = match ::attr::first_attr_value_str_by_name( outer_attrs, ~"path") { @@ -3505,7 +3508,8 @@ pub impl Parser { if self.eat_keyword(&~"fn") { impure_fn } else if self.eat_keyword(&~"pure") { self.expect_keyword(&~"fn"); - pure_fn + // NB: We parse this as impure for bootstrapping purposes. + impure_fn } else if self.eat_keyword(&~"unsafe") { self.expect_keyword(&~"fn"); unsafe_fn @@ -3894,8 +3898,9 @@ pub impl Parser { maybe_append(attrs, extra_attrs))); } else if items_allowed && self.eat_keyword(&~"pure") { // PURE FUNCTION ITEM + // NB: We parse this as impure for bootstrapping purposes. self.expect_keyword(&~"fn"); - let (ident, item_, extra_attrs) = self.parse_item_fn(pure_fn); + let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 7f46e45229998..492ecdb3f4de5 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -452,9 +452,10 @@ pub impl Printer { self.pending_indentation += amount; } fn get_top(&mut self) -> print_stack_elt { - let n = self.print_stack.len(); + let print_stack = &mut *self.print_stack; + let n = print_stack.len(); if n != 0u { - self.print_stack[n - 1u] + print_stack[n - 1u] } else { print_stack_elt { offset: 0, @@ -496,7 +497,8 @@ pub impl Printer { } END => { debug!("print END -> pop END"); - fail_unless!((self.print_stack.len() != 0u)); + let print_stack = &*self.print_stack; + fail_unless!((print_stack.len() != 0u)); self.print_stack.pop(); } BREAK(b) => { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5aae5570dbfee..71f3de174140c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -279,9 +279,10 @@ pub fn is_bol(s: @ps) -> bool { } pub fn in_cbox(s: @ps) -> bool { - let len = s.boxes.len(); + let boxes = &*s.boxes; + let len = boxes.len(); if len == 0u { return false; } - return s.boxes[len - 1u] == pp::consistent; + return boxes[len - 1u] == pp::consistent; } pub fn hardbreak_if_not_bol(s: @ps) { if !is_bol(s) { hardbreak(s.s); } } diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 7a5708049e9f4..47f49ebadaabf 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -41,14 +41,18 @@ pub impl Interner { None => (), } - let new_idx = self.vect.len(); + let vect = &*self.vect; + let new_idx = vect.len(); self.map.insert(val, new_idx); self.vect.push(val); new_idx } fn gensym(&self, val: T) -> uint { - let new_idx = self.vect.len(); + let new_idx = { + let vect = &*self.vect; + vect.len() + }; // leave out of .map to avoid colliding self.vect.push(val); new_idx @@ -59,7 +63,7 @@ pub impl Interner { // where we first check a pred and then rely on it, ceasing to fail is ok. pure fn get(&self, idx: uint) -> T { self.vect[idx] } - fn len(&self) -> uint { self.vect.len() } + fn len(&self) -> uint { let vect = &*self.vect; vect.len() } } #[test] diff --git a/src/test/compile-fail/borrowck-pat-enum-in-box.rs b/src/test/compile-fail/borrowck-pat-enum-in-box.rs index fe5f474a5f252..bd1001bf38cb7 100644 --- a/src/test/compile-fail/borrowck-pat-enum-in-box.rs +++ b/src/test/compile-fail/borrowck-pat-enum-in-box.rs @@ -22,17 +22,6 @@ fn match_const_box(v: &const @const Option) -> int { } } -pure fn pure_process(_i: int) {} - -fn match_const_box_and_do_pure_things(v: &const @const Option) { - match *v { - @Some(ref i) => { - pure_process(*i) - } - @None => {} - } -} - fn process(_i: int) {} fn match_const_box_and_do_bad_things(v: &const @const Option) { diff --git a/src/test/compile-fail/borrowck-pure-scope-in-call.rs b/src/test/compile-fail/borrowck-pure-scope-in-call.rs deleted file mode 100644 index 7ff13739ba7e6..0000000000000 --- a/src/test/compile-fail/borrowck-pure-scope-in-call.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pure fn pure_borrow(_x: &int, _y: ()) {} - -fn test1(x: @mut ~int) { - // Here, evaluating the second argument actually invalidates the - // first borrow, even though it occurs outside of the scope of the - // borrow! - pure_borrow(*x, *x = ~5); //~ ERROR illegal borrow unless pure - //~^ NOTE impure due to assigning to dereference of mutable @ pointer -} - -fn test2() { - let mut x = ~1; - - // Same, but for loanable data: - - pure_borrow(x, x = ~5); //~ ERROR assigning to mutable local variable prohibited due to outstanding loan - //~^ NOTE loan of mutable local variable granted here - - copy x; -} - -fn main() { -} diff --git a/src/test/compile-fail/nontrivial-fn-arg-pattern-in-pure-fn.rs b/src/test/compile-fail/nontrivial-fn-arg-pattern-in-pure-fn.rs deleted file mode 100644 index c60eec6edd555..0000000000000 --- a/src/test/compile-fail/nontrivial-fn-arg-pattern-in-pure-fn.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pure fn call_first((x, _y): (&fn(), &fn())) { - x(); //~ ERROR access to impure function prohibited in pure context -} - -fn main() {} - diff --git a/src/test/compile-fail/pure-higher-order.rs b/src/test/compile-fail/pure-higher-order.rs deleted file mode 100644 index 6d262bc04e1e4..0000000000000 --- a/src/test/compile-fail/pure-higher-order.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[legacy_modes]; - -// Test rules governing higher-order pure fns. - -struct S<'self> { - f: &'self fn(uint) -} - -pure fn range(from: uint, to: uint, f: &fn(uint)) { - let mut i = from; - while i < to { - f(i); // Note: legal to call argument, even if it is not pure. - i += 1u; - } -} - -pure fn range2(from: uint, to: uint, f: &fn(uint)) { - do range(from, to) |i| { - f(i*2u); - } -} - -pure fn range3(from: uint, to: uint, f: &fn(uint)) { - range(from, to, f) -} - -pure fn range4(from: uint, to: uint) { - range(from, to, print) //~ ERROR access to impure function prohibited in pure context -} - -pure fn range5<'a>(from: uint, to: uint, x: S<'a>) { - range(from, to, x.f) //~ ERROR access to impure function prohibited in pure context -} - -pure fn range6<'a>(from: uint, to: uint, x: @S<'a>) { - range(from, to, x.f) //~ ERROR access to impure function prohibited in pure context -} - -pure fn range7(from: uint, to: uint) { - do range(from, to) |i| { - print(i); //~ ERROR access to impure function prohibited in pure context - } -} - -pure fn range8(from: uint, to: uint) { - range(from, to, noop); -} - -fn print(i: uint) { error!("i=%u", i); } - -pure fn noop(_i: uint) {} - -fn main() { -} diff --git a/src/test/compile-fail/pure-loop-body.rs b/src/test/compile-fail/pure-loop-body.rs deleted file mode 100644 index 43a54981dcb71..0000000000000 --- a/src/test/compile-fail/pure-loop-body.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct S<'self> { - x: &'self fn(uint) -} - -pure fn range<'a>(from: uint, to: uint, f: &'a fn(uint) -> bool) { - let mut i = from; - while i < to { - if !f(i) {return;} // Note: legal to call argument, even if it is not pure. - i += 1u; - } -} - -pure fn range2<'a>(from: uint, to: uint, f: &'a fn(uint)) { - for range(from, to) |i| { - f(i*2u); - } -} - -pure fn range3<'a>(from: uint, to: uint, f: S<'a>) { - for range(from, to) |i| { - (f.x)(i*2u); //~ ERROR access to impure function prohibited - } -} - -fn main() {} diff --git a/src/test/compile-fail/pure-modifies-aliased.rs b/src/test/compile-fail/pure-modifies-aliased.rs deleted file mode 100644 index 4bd56c6e78b01..0000000000000 --- a/src/test/compile-fail/pure-modifies-aliased.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Check that pure functions cannot modify aliased state. - -struct S { - f: int, -} - -pure fn modify_in_box(sum: @mut S) { - sum.f = 3; //~ ERROR assigning to mutable field prohibited in pure context -} - -trait modify_in_box_rec { - pure fn modify_in_box_rec(&self, sum: @mut S); -} - -impl modify_in_box_rec for int { - pure fn modify_in_box_rec(&self, sum: @mut S) { - sum.f = *self; //~ ERROR assigning to mutable field prohibited in pure context - } -} - -fn main() { -} diff --git a/src/test/compile-fail/pure-subtyping.rs b/src/test/compile-fail/pure-subtyping.rs deleted file mode 100644 index 2744afb113d5f..0000000000000 --- a/src/test/compile-fail/pure-subtyping.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test rules governing higher-order pure fns. - -fn take(_v: T) {} - -fn assign_to_pure(x: &pure fn(), y: &fn(), z: &unsafe fn()) { - take::<&pure fn()>(x); - take::<&pure fn()>(y); //~ ERROR expected pure fn but found impure fn - take::<&pure fn()>(z); //~ ERROR expected pure fn but found unsafe fn -} - -fn assign_to_impure(x: &pure fn(), y: &fn(), z: &unsafe fn()) { - take::<&fn()>(x); - take::<&fn()>(y); - take::<&fn()>(z); //~ ERROR expected impure fn but found unsafe fn -} - -fn assign_to_unsafe(x: &pure fn(), y: &fn(), z: &unsafe fn()) { - take::<&unsafe fn()>(x); - take::<&unsafe fn()>(y); - take::<&unsafe fn()>(z); -} - -fn assign_to_pure2(x: @pure fn(), y: @fn(), z: @unsafe fn()) { - take::<&pure fn()>(x); - take::<&pure fn()>(y); //~ ERROR expected pure fn but found impure fn - take::<&pure fn()>(z); //~ ERROR expected pure fn but found unsafe fn - - take::<~pure fn()>(x); //~ ERROR expected ~ closure, found @ closure - take::<~pure fn()>(y); //~ ERROR expected ~ closure, found @ closure - take::<~pure fn()>(z); //~ ERROR expected ~ closure, found @ closure - - take::<~unsafe fn()>(x); //~ ERROR expected ~ closure, found @ closure - take::<~unsafe fn()>(y); //~ ERROR expected ~ closure, found @ closure - take::<~unsafe fn()>(z); //~ ERROR expected ~ closure, found @ closure -} - -fn main() { -} diff --git a/src/test/compile-fail/purity-infer-fail.rs b/src/test/compile-fail/purity-infer-fail.rs deleted file mode 100644 index 3e5296530fa35..0000000000000 --- a/src/test/compile-fail/purity-infer-fail.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn something(f: &pure fn()) { f(); } - -fn main() { - let mut x = ~[]; - something(|| x.push(0) ); //~ ERROR access to impure function prohibited in pure context -} diff --git a/src/test/compile-fail/trait-impl-method-mismatch.rs b/src/test/compile-fail/trait-impl-method-mismatch.rs index 6931e680e08f2..6676cde3c96a6 100644 --- a/src/test/compile-fail/trait-impl-method-mismatch.rs +++ b/src/test/compile-fail/trait-impl-method-mismatch.rs @@ -9,15 +9,15 @@ // except according to those terms. trait Mumbo { - pure fn jumbo(&self, x: @uint) -> uint; + fn jumbo(&self, x: @uint) -> uint; fn jambo(&self, x: @const uint) -> uint; fn jbmbo(&self) -> @uint; } impl Mumbo for uint { // Cannot have a larger effect than the trait: - fn jumbo(&self, x: @uint) { *self + *x; } - //~^ ERROR expected pure fn but found impure fn + unsafe fn jumbo(&self, x: @uint) { *self + *x; } + //~^ ERROR expected impure fn but found unsafe fn // Cannot accept a narrower range of parameters: fn jambo(&self, x: @uint) { *self + *x; } diff --git a/src/test/run-pass/auto-ref-slice-plus-ref.rs b/src/test/run-pass/auto-ref-slice-plus-ref.rs index ea41a50e382bb..39fe34bfe5286 100644 --- a/src/test/run-pass/auto-ref-slice-plus-ref.rs +++ b/src/test/run-pass/auto-ref-slice-plus-ref.rs @@ -39,7 +39,6 @@ pub fn main() { (&"test").test_imm(); // XXX: Other types of mutable vecs don't currently exist - (@mut [1]).test_imm(); ([1]).test_const(); (~[1]).test_const(); @@ -50,8 +49,6 @@ pub fn main() { (@"test").test_const(); (&"test").test_const(); - (@mut [1]).test_const(); - // NB: We don't do this double autoreffing for &mut self because that would // allow creating a mutable pointer to a temporary, which would be a source // of confusion diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index 0c285258f7522..a0a4ea19964f7 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -62,8 +62,8 @@ impl BaseIter<(int, &'self T)> for cat { } impl Container for cat { - pure fn len(&self) -> uint { self.meows as uint } - pure fn is_empty(&self) -> bool { self.meows == 0 } + pure fn len(&const self) -> uint { self.meows as uint } + pure fn is_empty(&const self) -> bool { self.meows == 0 } } impl Mutable for cat { diff --git a/src/test/run-pass/coerce-reborrow-imm-ptr-arg.rs b/src/test/run-pass/coerce-reborrow-imm-ptr-arg.rs index 37770f4d59ba5..905046756f6ee 100644 --- a/src/test/run-pass/coerce-reborrow-imm-ptr-arg.rs +++ b/src/test/run-pass/coerce-reborrow-imm-ptr-arg.rs @@ -10,8 +10,4 @@ fn negate_imm(y: &int) -> int { negate(y) } -fn negate_const(y: &const int) -> int { - negate(y) -} - pub fn main() {} diff --git a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs index 8fab061b4de30..54d9758aa2145 100644 --- a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs @@ -3,7 +3,7 @@ struct SpeechMaker { } pub impl SpeechMaker { - pure fn how_many(&self) -> uint { self.speeches } + pure fn how_many(&const self) -> uint { self.speeches } } fn foo(speaker: &const SpeechMaker) -> uint { diff --git a/src/test/run-pass/coerce-reborrow-imm-vec-arg.rs b/src/test/run-pass/coerce-reborrow-imm-vec-arg.rs index ba7d78ba04f11..a18b4a2b0c691 100644 --- a/src/test/run-pass/coerce-reborrow-imm-vec-arg.rs +++ b/src/test/run-pass/coerce-reborrow-imm-vec-arg.rs @@ -1,3 +1,5 @@ +// xfail-test + pure fn sum(x: &[int]) -> int { let mut sum = 0; for x.each |y| { sum += *y; } diff --git a/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs b/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs index 7ab63f43769cf..bf86472d900d7 100644 --- a/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs @@ -1,3 +1,5 @@ +// xfail-test + fn foo(v: &[const uint]) -> ~[uint] { v.to_vec() } diff --git a/src/test/run-pass/lambda-infer-unresolved.rs b/src/test/run-pass/lambda-infer-unresolved.rs index 3f94600ea17d3..2e70e90038971 100644 --- a/src/test/run-pass/lambda-infer-unresolved.rs +++ b/src/test/run-pass/lambda-infer-unresolved.rs @@ -16,6 +16,6 @@ struct Refs { refs: ~[int], n: int } pub fn main() { let e = @mut Refs{refs: ~[], n: 0}; - let f: @fn() = || error!(e.n); + let f: @fn() = || error!(copy e.n); e.refs += ~[1]; }