if impl
let loop
match mod mut
-priv pub pure
+priv pub
ref return
self static struct super
true trait type
- 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
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
~~~~
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);
~~~~
### 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:
~~~
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
# 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}
}
~~~
# }
# 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
# 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}
}
~~~
# }
# 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}
}
~~~
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use cast::transmute;
use option;
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) }
// 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;
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
}
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 {
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> {
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> {
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);
}
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 }
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 => {}
}
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 => {}
}
}
#[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)
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
}
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;
}
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)]
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)]
}
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(", ");
_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(')');
// 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
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> {
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 {
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.
*
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> {
/// 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
+ }
}
}
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;
}
-> 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 {
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());
}
}
}
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
}
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);
}
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
None => return,
Some(loans) => loans
};
+ let new_loans: &mut ~[Loan] = new_loans;
debug!("new_loans has length %?", new_loans.len());
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);
+ }
}
}
}
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=%?)",
// 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)
// 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> {
}
}
- fn add_loans(@mut self,
+ fn add_loans(&mut self,
cmt: cmt,
loan_kind: LoanKind,
scope_r: ty::Region,
}
}
- 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",
_ => 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 {
// 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);
+ }
+ }
}
- }
}
}
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
def_id: def_id,
kind: kind,
children: @HashMap(),
- imports: ~[],
+ imports: @mut ~[],
anonymous_children: @HashMap(),
import_resolutions: @HashMap(),
glob_count: 0,
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;
}
}
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))
}
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.
(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;
}
_ => ()
}
- match t.bindings.value_def {
+ match bindings.value_def {
Some(ref value_def) => {
if value_def.privacy == Private {
return Failed;
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.
*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) {
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 => {
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.
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);
// 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));
}
}
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);
}
}
}
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, _) => {
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
}
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);
// 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;
}
}
// 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 {
}
_ => ()
}
- cur = match cur.parent {
+ cur = match current.parent {
Some(next) => next,
None => return false
}
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.
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)
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));
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;
}
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;
// 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),
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),
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,
use core::prelude::*;
+use middle::resolve::Impl;
use middle::ty::{param_ty, substs};
use middle::ty;
use middle::typeck::check::{FnCtxt, impl_self_ty};
// 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| {
}
}
- 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]);
}
}
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(),
}
}
}
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 {
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> {
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()) {
}
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());
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()
}
}
// 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 {
}
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
}
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",
}
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| {
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 {
}
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> {
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,
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,
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,
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,
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> {
}
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;
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> {
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;
}
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;
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;
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;
}
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;
}
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;
}
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;
}
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()));
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> {
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> {
// 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);
}
+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
};
}
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";
}
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 {
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};
}
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(),
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(),
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, \
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(),
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);
}
}
~"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| {
+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,
}
-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(_) => {
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,
}
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) {
}
-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 } {
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{
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
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 {
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 {
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") {
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
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)));
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,
}
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) => {
}
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); } }
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
// 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]
}
}
-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>) {
+++ /dev/null
-// 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() {
-}
+++ /dev/null
-// 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() {}
-
+++ /dev/null
-// 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() {
-}
+++ /dev/null
-// 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() {}
+++ /dev/null
-// 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() {
-}
+++ /dev/null
-// 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() {
-}
+++ /dev/null
-// 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
-}
// 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; }
(&"test").test_imm();
// XXX: Other types of mutable vecs don't currently exist
- (@mut [1]).test_imm();
([1]).test_const();
(~[1]).test_const();
(@"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
}
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> {
negate(y)
}
-fn negate_const(y: &const int) -> int {
- negate(y)
-}
-
pub fn main() {}
}
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 {
+// xfail-test
+
pure fn sum(x: &[int]) -> int {
let mut sum = 0;
for x.each |y| { sum += *y; }
+// xfail-test
+
fn foo(v: &[const uint]) -> ~[uint] {
v.to_vec()
}
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];
}