Skip to content

Commit 34b42ee

Browse files
committed
change list so that it must be used in a purely boxed fashion
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.
1 parent 8e73bb6 commit 34b42ee

12 files changed

+127
-128
lines changed

src/libstd/arena.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
export arena, arena_with_size;
44

55
import list;
6+
import list::{list, cons, nil};
67

78
type chunk = {data: [u8], mut fill: uint};
8-
type arena = {mut chunks: list::list<@chunk>};
9+
type arena = {mut chunks: @list<@chunk>};
910

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

1617
fn arena_with_size(initial_size: uint) -> arena {
17-
ret {mut chunks: list::cons(chunk(initial_size), @list::nil)};
18+
ret {mut chunks: @cons(chunk(initial_size), @nil)};
1819
}
1920

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

3334
ret self.alloc(n_bytes, align);
3435
}

src/libstd/list.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ enum list<T> {
1111

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

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

8484
#[doc = "Returns all but the first element of a list"]
85-
pure fn tail<T: copy>(ls: @list<T>) -> list<T> {
85+
pure fn tail<T: copy>(ls: @list<T>) -> @list<T> {
8686
alt *ls {
8787
cons(_, tl) { ret tl; }
8888
nil { fail "list empty" }
@@ -98,7 +98,7 @@ pure fn head<T: copy>(ls: @list<T>) -> T {
9898
pure fn append<T: copy>(l: @list<T>, m: @list<T>) -> @list<T> {
9999
alt *l {
100100
nil { ret m; }
101-
cons(x, xs) { let rest = append(*xs, m); ret @cons(x, @rest); }
101+
cons(x, xs) { let rest = append(xs, m); ret @cons(x, rest); }
102102
}
103103
}
104104

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

119119
#[doc = "Iterate over a list"]
120-
fn each<T>(l: list<T>, f: fn(T) -> bool) {
120+
fn each<T>(l: @list<T>, f: fn(T) -> bool) {
121121
let mut cur = l;
122122
loop {
123123
cur = alt *cur {
124124
cons(hd, tl) {
125125
if !f(hd) { ret; }
126+
tl
126127
}
127128
nil { break; }
128129
}
@@ -163,7 +164,7 @@ mod tests {
163164
#[test]
164165
fn test_from_vec_empty() {
165166
let empty : @list::list<int> = from_vec([]);
166-
assert (empty == list::nil::<int>);
167+
assert (empty == @list::nil::<int>);
167168
}
168169

169170
#[test]
@@ -208,7 +209,7 @@ mod tests {
208209
fn test_find_fail() {
209210
fn match(&&_i: int) -> bool { ret false; }
210211
let l = from_vec([0, 1, 2]);
211-
let empty = list::nil::<int>;
212+
let empty = @list::nil::<int>;
212213
assert (list::find(l, match) == option::none::<int>);
213214
assert (list::find(empty, match) == option::none::<int>);
214215
}

src/rustc/middle/alias.rs

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type binding = @{node_id: node_id,
3333

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

3838
fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option<node_id>,
3939
unsafe_tys: [unsafe_ty]) -> binding {
@@ -68,7 +68,7 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (copy_map, ref_map) {
6868
visit_expr: bind visit_expr(cx, _, _, _),
6969
visit_block: bind visit_block(cx, _, _, _)
7070
with *visit::default_visitor::<scope>()};
71-
let sc = {bs: [], invalid: @mut list::nil};
71+
let sc = {bs: [], invalid: @mut @list::nil};
7272
visit::visit_crate(*crate, sc, visit::mk_vt(v));
7373
tcx.sess.abort_if_errors();
7474
ret (cx.copy_map, cx.ref_map);
@@ -88,7 +88,7 @@ fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl,
8888
check_loop(*cx, sc) {|| v.visit_block(body, sc, v);}
8989
}
9090
ast::proto_box | ast::proto_uniq | ast::proto_bare {
91-
let sc = {bs: [], invalid: @mut list::nil};
91+
let sc = {bs: [], invalid: @mut @list::nil};
9292
v.visit_block(body, sc, v);
9393
}
9494
}
@@ -400,7 +400,7 @@ fn check_var(cx: ctx, ex: @ast::expr, p: @ast::path, id: ast::node_id,
400400
if ty_can_unsafely_include(cx, unsafe_ty, var_t, assign) {
401401
let inv = @{reason: val_taken, node_id: b.node_id,
402402
sp: ex.span, path: p};
403-
*sc.invalid = list::cons(inv, @*sc.invalid);
403+
*sc.invalid = @list::cons(inv, *sc.invalid);
404404
}
405405
}
406406
} else if b.node_id == my_defnum {
@@ -418,7 +418,7 @@ fn check_lval(cx: @ctx, dest: @ast::expr, sc: scope, v: vt<scope>) {
418418
if b.root_var == some(dnum) {
419419
let inv = @{reason: overwritten, node_id: b.node_id,
420420
sp: dest.span, path: p};
421-
*sc.invalid = list::cons(inv, @*sc.invalid);
421+
*sc.invalid = @list::cons(inv, *sc.invalid);
422422
}
423423
}
424424
}
@@ -791,46 +791,43 @@ fn unsafe_set(from: option<unsafe_ty>) -> [unsafe_ty] {
791791
alt from { some(t) { [t] } _ { [] } }
792792
}
793793

794-
fn find_invalid(id: node_id, lst: list<@invalid>)
795-
-> option<@invalid> {
794+
fn find_invalid(id: node_id, lst: @list<@invalid>) -> option<@invalid> {
796795
let mut cur = lst;
797796
loop {
798-
alt cur {
797+
alt *cur {
799798
list::nil { ret none; }
800799
list::cons(head, tail) {
801800
if head.node_id == id { ret some(head); }
802-
cur = *tail;
801+
cur = tail;
803802
}
804803
}
805804
};
806805
}
807806

808-
fn join_invalid(a: list<@invalid>, b: list<@invalid>) -> list<@invalid> {
807+
fn join_invalid(a: @list<@invalid>, b: @list<@invalid>) -> @list<@invalid> {
809808
let mut result = a;
810809
list::iter(b) {|elt|
811810
let mut found = false;
812811
list::iter(a) {|e| if e == elt { found = true; } }
813-
if !found { result = list::cons(elt, @result); }
812+
if !found { result = @list::cons(elt, result); }
814813
}
815814
result
816815
}
817816

818-
fn filter_invalid(src: list<@invalid>, bs: [binding]) -> list<@invalid> {
819-
let mut out = list::nil, cur = src;
820-
while cur != list::nil {
821-
alt cur {
817+
fn filter_invalid(src: @list<@invalid>, bs: [binding]) -> @list<@invalid> {
818+
let mut out = @list::nil, cur = src;
819+
loop {
820+
alt *cur {
822821
list::cons(head, tail) {
823822
let p = vec::position(bs, {|b| b.node_id == head.node_id});
824-
if !is_none(p) { out = list::cons(head, @out); }
825-
cur = *tail;
823+
if !is_none(p) { out = @list::cons(head, out); }
824+
cur = tail;
826825
}
827826
list::nil {
828-
// typestate would help...
829-
unreachable();
827+
ret out;
830828
}
831829
}
832830
}
833-
ret out;
834831
}
835832

836833
fn err(cx: ctx, sp: span, err: str) {

src/rustc/middle/last_use.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ enum seen { unset, seen(node_id), }
3737
enum block_type { func, lp, }
3838

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

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

5757
fn find_last_uses(c: @crate, def_map: resolve::def_map,
5858
ref_map: alias::ref_map, tcx: ty::ctxt)
@@ -67,7 +67,7 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
6767
ref_map: ref_map,
6868
tcx: tcx,
6969
mut current: [],
70-
mut blocks: nil};
70+
mut blocks: @nil};
7171
visit::visit_crate(*c, cx, v);
7272
let mini_table = std::map::int_hash();
7373
for cx.last_uses.each {|key, val|
@@ -136,7 +136,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
136136
option::iter(def_is_owned_local(cx, my_def)) {|nid|
137137
clear_in_current(cx, nid, false);
138138
cx.current += [{def: nid,
139-
uses: cons(var_use(ex.id), @nil)}];
139+
uses: @cons(var_use(ex.id), @nil)}];
140140
}
141141
}
142142
}
@@ -249,13 +249,13 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
249249
option::iter(def_is_owned_local(cx, v.def)) {|nid|
250250
clear_in_current(cx, nid, false);
251251
cx.current += [{def: nid,
252-
uses: cons(close_over(id), @nil)}];
252+
uses: @cons(close_over(id), @nil)}];
253253
}
254254
}
255255
}
256256
_ {}
257257
}
258-
let mut old_cur = [], old_blocks = nil;
258+
let mut old_cur = [], old_blocks = @nil;
259259
cx.blocks <-> old_blocks;
260260
cx.current <-> old_cur;
261261
visit::visit_fn(fk, decl, body, sp, id, cx, v);
@@ -268,7 +268,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
268268

269269
fn visit_block(tp: block_type, cx: ctx, visit: fn()) {
270270
let local = @{type: tp, mut second: false, mut exits: []};
271-
cx.blocks = cons(local, @cx.blocks);
271+
cx.blocks = @cons(local, cx.blocks);
272272
visit();
273273
local.second = true;
274274
local.exits = [];
@@ -281,23 +281,20 @@ fn visit_block(tp: block_type, cx: ctx, visit: fn()) {
281281

282282
fn add_block_exit(cx: ctx, tp: block_type) -> bool {
283283
let mut cur = cx.blocks;
284-
while cur != nil {
285-
alt cur {
284+
loop {
285+
alt *cur {
286286
cons(b, tail) {
287287
if (b.type == tp) {
288288
if !b.second { b.exits += [cx.current]; }
289289
ret true;
290290
}
291-
cur = *tail;
291+
cur = tail;
292292
}
293293
nil {
294-
// typestate can't use the while loop condition --
295-
// *sigh*
296-
unreachable();
294+
ret false;
297295
}
298296
}
299297
}
300-
ret false;
301298
}
302299

303300
fn join_branches(branches: [set]) -> set {
@@ -312,7 +309,7 @@ fn join_branches(branches: [set]) -> set {
312309
for vec::each(branches[j]) {|elt2|
313310
if elt2.def == elt.def {
314311
list::iter(elt2.uses) {|e|
315-
if !list::has(nne, e) { nne = cons(e, @nne); }
312+
if !list::has(nne, e) { nne = @cons(e, nne); }
316313
}
317314
}
318315
}

0 commit comments

Comments
 (0)