diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs index 5c8f496d16bf..540716550ce8 100644 --- a/src/comp/middle/freevars.rs +++ b/src/comp/middle/freevars.rs @@ -18,8 +18,8 @@ export freevar_set; export freevar_map; export get_freevars; export has_freevars; -export is_freevarof; - +export is_freevar_of; +export def_lookup; type freevar_set = @ast::node_id[]; type freevar_map = hashmap[ast::node_id, freevar_set]; @@ -138,10 +138,10 @@ fn annotate_freevars(&session::session sess, &resolve::def_map def_map, fn get_freevars(&ty::ctxt tcx, ast::node_id fid) -> freevar_set { alt (tcx.freevars.find(fid)) { - case (none) { + none { fail "get_freevars: " + int::str(fid) + " has no freevars"; } - case (some(?d)) { ret d; } + some(?d) { ret d; } } } fn has_freevars(&ty::ctxt tcx, ast::node_id fid) -> bool { @@ -150,6 +150,19 @@ fn has_freevars(&ty::ctxt tcx, ast::node_id fid) -> bool { fn is_freevar_of(&ty::ctxt tcx, ast::node_id var, ast::node_id f) -> bool { ret ivec::member(var, *get_freevars(tcx, f)); } +fn def_lookup(&ty::ctxt tcx, ast::node_id f, ast::node_id id) -> + option::t[ast::def] { + alt (tcx.def_map.find(id)) { + none { ret none; } + some(?d) { + auto did = ast::def_id_of_def(d); + if is_freevar_of(tcx, did._1, f) { + ret some(ast::def_upvar(did, @d)); + } else { ret some(d); } + } + } +} + // Local Variables: // mode: rust diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 5992a857d148..a9367724c5ed 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -52,6 +52,11 @@ tag def { def_use(def_id); def_native_ty(def_id); def_native_fn(def_id); + + /* A "fake" def for upvars. This never appears in the def_map, but + * freevars::def_lookup will return it for a def that is an upvar. + * It contains the actual def. */ + def_upvar(def_id, @def); } fn variant_def_ids(&def d) -> tup(def_id, def_id) { @@ -76,6 +81,7 @@ fn def_id_of_def(def d) -> def_id { case (def_use(?id)) { ret id; } case (def_native_ty(?id)) { ret id; } case (def_native_fn(?id)) { ret id; } + case (def_upvar(?id, _)) { ret id; } } fail; }