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:
parent
c4db4faefa
commit
e78f2e2ac5
45
doc/rust.md
45
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<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:
|
||||
|
@ -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}
|
||||
}
|
||||
~~~
|
||||
|
@ -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) }
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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> {
|
||||
|
@ -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 }
|
||||
|
@ -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 => {}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -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(')');
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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| {
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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> {
|
||||
|
@ -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());
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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> {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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> {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()));
|
||||
|
@ -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> {
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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, \
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 } {
|
||||
|
@ -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
|
||||
|
@ -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)));
|
||||
|
@ -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) => {
|
||||
|
@ -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); } }
|
||||
|
@ -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]
|
||||
|
@ -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>) {
|
||||
|
@ -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() {
|
||||
}
|
@ -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() {}
|
||||
|
@ -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() {
|
||||
}
|
@ -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() {}
|
@ -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() {
|
||||
}
|
@ -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() {
|
||||
}
|
@ -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
|
||||
}
|
@ -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; }
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -10,8 +10,4 @@ fn negate_imm(y: &int) -> int {
|
||||
negate(y)
|
||||
}
|
||||
|
||||
fn negate_const(y: &const int) -> int {
|
||||
negate(y)
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
@ -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 {
|
||||
|
@ -1,3 +1,5 @@
|
||||
// xfail-test
|
||||
|
||||
pure fn sum(x: &[int]) -> int {
|
||||
let mut sum = 0;
|
||||
for x.each |y| { sum += *y; }
|
||||
|
@ -1,3 +1,5 @@
|
||||
// xfail-test
|
||||
|
||||
fn foo(v: &[const uint]) -> ~[uint] {
|
||||
v.to_vec()
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user