librustc: Make the compiler ignore purity.

For bootstrapping purposes, this commit does not remove all uses of
the keyword "pure" -- doing so would cause the compiler to no longer
bootstrap due to some syntax extensions ("deriving" in particular).
Instead, it makes the compiler ignore "pure". Post-snapshot, we can
remove "pure" from the language.

There are quite a few (~100) borrow check errors that were essentially
all the result of mutable fields or partial borrows of `@mut`. Per
discussions with Niko I think we want to allow partial borrows of
`@mut` but detect obvious footguns. We should also improve the error
message when `@mut` is erroneously reborrowed.
This commit is contained in:
Patrick Walton 2013-03-16 11:11:31 -07:00
parent c4db4faefa
commit e78f2e2ac5
72 changed files with 373 additions and 540 deletions

View File

@ -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<T>(ls: List<T>) -> uint { ... }
pure fn nonempty_list<T>(ls: List<T>) -> 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:

View File

@ -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<T>(shape: &r/Shape, threshold: float,
a: &r/T, b: &r/T) -> &r/T {
fn select<T>(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<T>(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<T>( // |-+ 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<T>( // |-+ 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<T>(shape: &tmp/Shape, threshold: float,
a: &r/T, b: &r/T) -> &r/T {
fn select<T>(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<T>(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}
}
~~~

View File

@ -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<T> {
mut value: Option<T>
}
impl<T:cmp::Eq> cmp::Eq for Cell<T> {
pure fn eq(&self, other: &Cell<T>) -> bool {
unsafe {
let frozen_self: &Option<T> = transmute(&mut self.value);
let frozen_other: &Option<T> = transmute(&mut other.value);
frozen_self == frozen_other
}
}
pure fn ne(&self, other: &Cell<T>) -> bool { !self.eq(other) }
}
/// Creates a new full cell with the given value.
pub fn Cell<T>(value: T) -> Cell<T> {
Cell { value: Some(value) }

View File

@ -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<T: Owned> Peekable<T> for PortSet<T> {
pure fn port_set_peek<T:Owned>(self: &PortSet<T>) -> 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<T> = cast::transmute(&mut self.ports[i]);
if port.peek() { return true }
}
}
false
}

View File

@ -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 {

View File

@ -290,10 +290,10 @@ pub mod linear {
impl<K:Hash + IterBytes + Eq,V> Container for LinearMap<K, V> {
/// 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<K:Hash + IterBytes + Eq,V> Mutable for LinearMap<K, V> {
@ -555,10 +555,10 @@ pub mod linear {
impl<T:Hash + IterBytes + Eq> Container for LinearSet<T> {
/// 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<T:Hash + IterBytes + Eq> Mutable for LinearSet<T> {

View File

@ -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 }

View File

@ -46,8 +46,7 @@ pub fn unwrap<T>(m: Mut<T>) -> T {
pub impl<T> Data<T> {
fn borrow_mut<R>(&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<T> Data<T> {
fn borrow_imm<R>(&self, op: &fn(t: &T) -> R) -> R {
match self.mode {
Mutable => fail!(fmt!("%? currently mutable",
self.value)),
Mutable => fail!(~"currently mutable"),
ReadOnly | Immutable => {}
}

View File

@ -228,14 +228,14 @@ pub pure fn while_some<T>(x: Option<T>, blk: &fn(v: T) -> Option<T>) {
}
#[inline(always)]
pub pure fn is_none<T>(opt: &Option<T>) -> bool {
pub pure fn is_none<T>(opt: &const Option<T>) -> bool {
//! Returns true if the option equals `none`
match *opt { None => true, Some(_) => false }
}
#[inline(always)]
pub pure fn is_some<T>(opt: &Option<T>) -> bool {
pub pure fn is_some<T>(opt: &const Option<T>) -> bool {
//! Returns true if the option contains some value
!is_none(opt)
@ -333,11 +333,11 @@ impl<T> MutableIter<T> for Option<T> {
pub impl<T> Option<T> {
/// 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

View File

@ -223,8 +223,8 @@ pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
}
pub trait Ptr<T> {
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<T> {
impl<T> Ptr<T> 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<T> Ptr<T> for *T {
impl<T> Ptr<T> 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)]

View File

@ -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(')');

View File

@ -127,7 +127,7 @@ type TaskGroupInner = &'self mut Option<TaskGroupData>;
// 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

View File

@ -50,11 +50,11 @@ impl<T> ReverseIter<(uint, &'self T)> for TrieMap<T> {
impl<T> Container for TrieMap<T> {
/// 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<T> Mutable for TrieMap<T> {
@ -178,11 +178,11 @@ impl ReverseIter<uint> 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 {

View File

@ -118,6 +118,14 @@ pub pure fn len<T>(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<T>(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<T> 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<T> {
@ -1707,7 +1715,14 @@ impl<T: Copy> CopyableVector<T> 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<A:Copy> iter::CopyableNonstrictIter<A> for &'self [A] {
impl<A:Copy> iter::CopyableNonstrictIter<A> 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;
}

View File

@ -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());
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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());

View File

@ -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<PreserveCondition> {
@ -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",

View File

@ -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 {

View File

@ -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);
}
}
}
}
}
}

View File

@ -457,7 +457,7 @@ pub struct Module {
kind: ModuleKind,
children: @HashMap<ident,@mut NameBindings>,
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;
}
}

View File

@ -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
}

View File

@ -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.

View File

@ -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)

View File

@ -845,7 +845,8 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata<SubProgramMetadata> {
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));

View File

@ -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;
}

View File

@ -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;

View File

@ -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),

View File

@ -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,

View File

@ -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| {

View File

@ -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]);
}

View File

@ -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(),
}
}

View File

@ -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 {

View File

@ -23,10 +23,10 @@ pub struct Deque<T> {
impl<T> Container for Deque<T> {
/// 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<T> Mutable for Deque<T> {

View File

@ -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());

View File

@ -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()
}
}

View File

@ -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

View File

@ -101,7 +101,7 @@ pub mod chained {
}
pure fn search_tbl(&self, k: &K, h: uint) -> SearchResult<K,V> {
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<K,V>) -> 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<K:Eq + IterBytes + Hash,V> Container for HashMap_<K, V> {
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<K:Eq + IterBytes + Hash,V> HashMap_<K, V> {
@ -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,

View File

@ -37,10 +37,10 @@ impl<T:Ord> BaseIter<T> for PriorityQueue<T> {
impl<T:Ord> Container for PriorityQueue<T> {
/// 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<T:Ord> Mutable for PriorityQueue<T> {

View File

@ -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;

View File

@ -50,18 +50,19 @@ impl<V> ReverseIter<(uint, &'self V)> for SmallIntMap<V> {
impl<V> Container for SmallIntMap<V> {
/// 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<V> Mutable for SmallIntMap<V> {

View File

@ -68,9 +68,14 @@ fn part<T>(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<T:Copy + Ord> MergeState<T> {
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<T:Copy + Ord> MergeState<T> {
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<T:Copy>(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::<int>(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::<int>(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::<int>(v1);
let mut i = 0u;
while i < len {
debug!(v2[i]);
// debug!(v2[i]);
fail_unless!((v2[i] == v1[i]));
i += 1u;
}

View File

@ -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()));

View File

@ -106,10 +106,10 @@ impl<'self, K: TotalOrd, V>
impl<K: TotalOrd, V> Container for TreeMap<K, V> {
/// 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<K: TotalOrd, V> Mutable for TreeMap<K, V> {
@ -276,11 +276,11 @@ impl<T: Ord + TotalOrd> Ord for TreeSet<T> {
impl<T: TotalOrd> Container for TreeSet<T> {
/// 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<T: TotalOrd> Mutable for TreeSet<T> {

View File

@ -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};
}

View File

@ -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(),

View File

@ -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, \

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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 } {

View File

@ -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

View File

@ -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)));

View File

@ -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) => {

View File

@ -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); } }

View File

@ -41,14 +41,18 @@ pub impl<T:Eq + IterBytes + Hash + Const + Copy> Interner<T> {
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<T:Eq + IterBytes + Hash + Const + Copy> Interner<T> {
// 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]

View File

@ -22,17 +22,6 @@ fn match_const_box(v: &const @const Option<int>) -> int {
}
}
pure fn pure_process(_i: int) {}
fn match_const_box_and_do_pure_things(v: &const @const Option<int>) {
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<int>) {

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(_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() {
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
}

View File

@ -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; }

View File

@ -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

View File

@ -62,8 +62,8 @@ impl<T> BaseIter<(int, &'self T)> for cat<T> {
}
impl<T> Container for cat<T> {
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<T> Mutable for cat<T> {

View File

@ -10,8 +10,4 @@ fn negate_imm(y: &int) -> int {
negate(y)
}
fn negate_const(y: &const int) -> int {
negate(y)
}
pub fn main() {}

View File

@ -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 {

View File

@ -1,3 +1,5 @@
// xfail-test
pure fn sum(x: &[int]) -> int {
let mut sum = 0;
for x.each |y| { sum += *y; }

View File

@ -1,3 +1,5 @@
// xfail-test
fn foo(v: &[const uint]) -> ~[uint] {
v.to_vec()
}

View File

@ -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];
}