Skip to content

Commit

Permalink
change list so that it must be used in a purely boxed fashion
Browse files Browse the repository at this point in the history
The old way was inconsistent---the head was unboxed but the
tail was boxed.  This resulted in numerous needless copies and
also made the borrow check unhappy, because the head tended to be
stored in mutable memory.
  • Loading branch information
nikomatsakis committed May 21, 2012
1 parent 8e73bb6 commit 34b42ee
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 128 deletions.
7 changes: 4 additions & 3 deletions src/libstd/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
export arena, arena_with_size;

import list;
import list::{list, cons, nil};

type chunk = {data: [u8], mut fill: uint};
type arena = {mut chunks: list::list<@chunk>};
type arena = {mut chunks: @list<@chunk>};

fn chunk(size: uint) -> @chunk {
let mut v = [];
Expand All @@ -14,7 +15,7 @@ fn chunk(size: uint) -> @chunk {
}

fn arena_with_size(initial_size: uint) -> arena {
ret {mut chunks: list::cons(chunk(initial_size), @list::nil)};
ret {mut chunks: @cons(chunk(initial_size), @nil)};
}

fn arena() -> arena {
Expand All @@ -28,7 +29,7 @@ impl arena for arena {
let chunk_size = vec::capacity(head.data);
let new_min_chunk_size = uint::max(n_bytes, chunk_size);
head = chunk(uint::next_power_of_two(new_min_chunk_size + 1u));
self.chunks = list::cons(head, @self.chunks);
self.chunks = @cons(head, self.chunks);

ret self.alloc(n_bytes, align);
}
Expand Down
15 changes: 8 additions & 7 deletions src/libstd/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ enum list<T> {

#[doc = "Create a list from a vector"]
fn from_vec<T: copy>(v: [const T]) -> @list<T> {
@vec::foldr(v, @nil::<T>, { |h, t| @cons(h, t) })
vec::foldr(v, @nil::<T>, { |h, t| @cons(h, t) })
}

#[doc = "
Expand Down Expand Up @@ -43,7 +43,7 @@ is returned. If `f` matches no elements then none is returned.
fn find<T: copy>(ls: @list<T>, f: fn(T) -> bool) -> option<T> {
let mut ls = ls;
loop {
ls = alt ls {
ls = alt *ls {
cons(hd, tl) {
if f(hd) { ret some(hd); }
tl
Expand Down Expand Up @@ -82,7 +82,7 @@ fn len<T>(ls: @list<T>) -> uint {
}

#[doc = "Returns all but the first element of a list"]
pure fn tail<T: copy>(ls: @list<T>) -> list<T> {
pure fn tail<T: copy>(ls: @list<T>) -> @list<T> {
alt *ls {
cons(_, tl) { ret tl; }
nil { fail "list empty" }
Expand All @@ -98,7 +98,7 @@ pure fn head<T: copy>(ls: @list<T>) -> T {
pure fn append<T: copy>(l: @list<T>, m: @list<T>) -> @list<T> {
alt *l {
nil { ret m; }
cons(x, xs) { let rest = append(*xs, m); ret @cons(x, @rest); }
cons(x, xs) { let rest = append(xs, m); ret @cons(x, rest); }
}
}

Expand All @@ -117,12 +117,13 @@ fn iter<T>(l: @list<T>, f: fn(T)) {
}

#[doc = "Iterate over a list"]
fn each<T>(l: list<T>, f: fn(T) -> bool) {
fn each<T>(l: @list<T>, f: fn(T) -> bool) {
let mut cur = l;
loop {
cur = alt *cur {
cons(hd, tl) {
if !f(hd) { ret; }
tl
}
nil { break; }
}
Expand Down Expand Up @@ -163,7 +164,7 @@ mod tests {
#[test]
fn test_from_vec_empty() {
let empty : @list::list<int> = from_vec([]);
assert (empty == list::nil::<int>);
assert (empty == @list::nil::<int>);
}

#[test]
Expand Down Expand Up @@ -208,7 +209,7 @@ mod tests {
fn test_find_fail() {
fn match(&&_i: int) -> bool { ret false; }
let l = from_vec([0, 1, 2]);
let empty = list::nil::<int>;
let empty = @list::nil::<int>;
assert (list::find(l, match) == option::none::<int>);
assert (list::find(empty, match) == option::none::<int>);
}
Expand Down
37 changes: 17 additions & 20 deletions src/rustc/middle/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type binding = @{node_id: node_id,

// FIXME it may be worthwhile to use a linked list of bindings instead
type scope = {bs: [binding],
invalid: @mut list<@invalid>};
invalid: @mut @list<@invalid>};

fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option<node_id>,
unsafe_tys: [unsafe_ty]) -> binding {
Expand Down Expand Up @@ -68,7 +68,7 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (copy_map, ref_map) {
visit_expr: bind visit_expr(cx, _, _, _),
visit_block: bind visit_block(cx, _, _, _)
with *visit::default_visitor::<scope>()};
let sc = {bs: [], invalid: @mut list::nil};
let sc = {bs: [], invalid: @mut @list::nil};
visit::visit_crate(*crate, sc, visit::mk_vt(v));
tcx.sess.abort_if_errors();
ret (cx.copy_map, cx.ref_map);
Expand All @@ -88,7 +88,7 @@ fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl,
check_loop(*cx, sc) {|| v.visit_block(body, sc, v);}
}
ast::proto_box | ast::proto_uniq | ast::proto_bare {
let sc = {bs: [], invalid: @mut list::nil};
let sc = {bs: [], invalid: @mut @list::nil};
v.visit_block(body, sc, v);
}
}
Expand Down Expand Up @@ -400,7 +400,7 @@ fn check_var(cx: ctx, ex: @ast::expr, p: @ast::path, id: ast::node_id,
if ty_can_unsafely_include(cx, unsafe_ty, var_t, assign) {
let inv = @{reason: val_taken, node_id: b.node_id,
sp: ex.span, path: p};
*sc.invalid = list::cons(inv, @*sc.invalid);
*sc.invalid = @list::cons(inv, *sc.invalid);
}
}
} else if b.node_id == my_defnum {
Expand All @@ -418,7 +418,7 @@ fn check_lval(cx: @ctx, dest: @ast::expr, sc: scope, v: vt<scope>) {
if b.root_var == some(dnum) {
let inv = @{reason: overwritten, node_id: b.node_id,
sp: dest.span, path: p};
*sc.invalid = list::cons(inv, @*sc.invalid);
*sc.invalid = @list::cons(inv, *sc.invalid);
}
}
}
Expand Down Expand Up @@ -791,46 +791,43 @@ fn unsafe_set(from: option<unsafe_ty>) -> [unsafe_ty] {
alt from { some(t) { [t] } _ { [] } }
}

fn find_invalid(id: node_id, lst: list<@invalid>)
-> option<@invalid> {
fn find_invalid(id: node_id, lst: @list<@invalid>) -> option<@invalid> {
let mut cur = lst;
loop {
alt cur {
alt *cur {
list::nil { ret none; }
list::cons(head, tail) {
if head.node_id == id { ret some(head); }
cur = *tail;
cur = tail;
}
}
};
}

fn join_invalid(a: list<@invalid>, b: list<@invalid>) -> list<@invalid> {
fn join_invalid(a: @list<@invalid>, b: @list<@invalid>) -> @list<@invalid> {
let mut result = a;
list::iter(b) {|elt|
let mut found = false;
list::iter(a) {|e| if e == elt { found = true; } }
if !found { result = list::cons(elt, @result); }
if !found { result = @list::cons(elt, result); }
}
result
}

fn filter_invalid(src: list<@invalid>, bs: [binding]) -> list<@invalid> {
let mut out = list::nil, cur = src;
while cur != list::nil {
alt cur {
fn filter_invalid(src: @list<@invalid>, bs: [binding]) -> @list<@invalid> {
let mut out = @list::nil, cur = src;
loop {
alt *cur {
list::cons(head, tail) {
let p = vec::position(bs, {|b| b.node_id == head.node_id});
if !is_none(p) { out = list::cons(head, @out); }
cur = *tail;
if !is_none(p) { out = @list::cons(head, out); }
cur = tail;
}
list::nil {
// typestate would help...
unreachable();
ret out;
}
}
}
ret out;
}

fn err(cx: ctx, sp: span, err: str) {
Expand Down
27 changes: 12 additions & 15 deletions src/rustc/middle/last_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ enum seen { unset, seen(node_id), }
enum block_type { func, lp, }

enum use { var_use(node_id), close_over(node_id), }
type set = [{def: node_id, uses: list<use>}];
type set = [{def: node_id, uses: @list<use>}];
type bl = @{type: block_type, mut second: bool, mut exits: [set]};

enum use_id { path(node_id), close(node_id, node_id) }
Expand All @@ -52,7 +52,7 @@ type ctx = {last_uses: std::map::hashmap<use_id, bool>,
tcx: ty::ctxt,
// The current set of local last uses
mut current: set,
mut blocks: list<bl>};
mut blocks: @list<bl>};

fn find_last_uses(c: @crate, def_map: resolve::def_map,
ref_map: alias::ref_map, tcx: ty::ctxt)
Expand All @@ -67,7 +67,7 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
ref_map: ref_map,
tcx: tcx,
mut current: [],
mut blocks: nil};
mut blocks: @nil};
visit::visit_crate(*c, cx, v);
let mini_table = std::map::int_hash();
for cx.last_uses.each {|key, val|
Expand Down Expand Up @@ -136,7 +136,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
option::iter(def_is_owned_local(cx, my_def)) {|nid|
clear_in_current(cx, nid, false);
cx.current += [{def: nid,
uses: cons(var_use(ex.id), @nil)}];
uses: @cons(var_use(ex.id), @nil)}];
}
}
}
Expand Down Expand Up @@ -249,13 +249,13 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
option::iter(def_is_owned_local(cx, v.def)) {|nid|
clear_in_current(cx, nid, false);
cx.current += [{def: nid,
uses: cons(close_over(id), @nil)}];
uses: @cons(close_over(id), @nil)}];
}
}
}
_ {}
}
let mut old_cur = [], old_blocks = nil;
let mut old_cur = [], old_blocks = @nil;
cx.blocks <-> old_blocks;
cx.current <-> old_cur;
visit::visit_fn(fk, decl, body, sp, id, cx, v);
Expand All @@ -268,7 +268,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,

fn visit_block(tp: block_type, cx: ctx, visit: fn()) {
let local = @{type: tp, mut second: false, mut exits: []};
cx.blocks = cons(local, @cx.blocks);
cx.blocks = @cons(local, cx.blocks);
visit();
local.second = true;
local.exits = [];
Expand All @@ -281,23 +281,20 @@ fn visit_block(tp: block_type, cx: ctx, visit: fn()) {

fn add_block_exit(cx: ctx, tp: block_type) -> bool {
let mut cur = cx.blocks;
while cur != nil {
alt cur {
loop {
alt *cur {
cons(b, tail) {
if (b.type == tp) {
if !b.second { b.exits += [cx.current]; }
ret true;
}
cur = *tail;
cur = tail;
}
nil {
// typestate can't use the while loop condition --
// *sigh*
unreachable();
ret false;
}
}
}
ret false;
}

fn join_branches(branches: [set]) -> set {
Expand All @@ -312,7 +309,7 @@ fn join_branches(branches: [set]) -> set {
for vec::each(branches[j]) {|elt2|
if elt2.def == elt.def {
list::iter(elt2.uses) {|e|
if !list::has(nne, e) { nne = cons(e, @nne); }
if !list::has(nne, e) { nne = @cons(e, nne); }
}
}
}
Expand Down
Loading

0 comments on commit 34b42ee

Please sign in to comment.