Skip to content

Commit 94d4dcd

Browse files
committed
Fix bug in handling of block functions in last-use analysis
It would fail to start out with a fresh scope when going over a loop or block function for the second time, and thus not recognize last uses of locals defined inside the block. Closes #1818
1 parent 520c3f5 commit 94d4dcd

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

src/comp/middle/last_use.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
137137
// n.b.: safe to ignore copies, as if they are unused
138138
// then they are ignored, otherwise they will show up
139139
// as freevars in the body.
140-
141140
vec::iter(cap_clause.moves) {|ci|
142141
clear_def_if_path(cx, cx.def_map.get(ci.id), true);
143142
}
@@ -203,13 +202,18 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
203202
fn visit_block(tp: block_type, cx: ctx, visit: fn()) {
204203
let local = @{type: tp, mutable second: false, mutable exits: []};
205204
cx.blocks = cons(local, @cx.blocks);
205+
let start_current = cx.current;
206206
visit();
207207
local.second = true;
208+
local.exits = [];
209+
cx.current = start_current;
208210
visit();
209211
let cx_blocks = cx.blocks;
210212
check is_not_empty(cx_blocks);
211213
cx.blocks = tail(cx_blocks);
212-
cx.current = join_branches(local.exits);
214+
let branches = if tp == func { local.exits + [cx.current] }
215+
else { local.exits };
216+
cx.current = join_branches(branches);
213217
}
214218

215219
fn add_block_exit(cx: ctx, tp: block_type) -> bool {
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Issue #1818
2+
3+
fn loop<T>(s: str, f: fn(str) -> T) -> T {
4+
while false {
5+
let r = f(s);
6+
ret r;
7+
}
8+
fail;
9+
}
10+
11+
fn apply<T>(s: str, f: fn(str) -> T) -> T {
12+
fn g<T>(s: str, f: fn(str) -> T) -> T {f(s)}
13+
g(s) {|v| let r = f(v); r }
14+
}
15+
16+
fn main() {}

0 commit comments

Comments
 (0)