Skip to content

Commit 10503a4

Browse files
committed
rustc: Don't rebuild the AST when writing back locals
1 parent 3ffe390 commit 10503a4

File tree

3 files changed

+94
-62
lines changed

3 files changed

+94
-62
lines changed

src/comp/middle/ty.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,17 +1671,7 @@ fn block_ty(&ctxt cx, &node_type_table ntt, &ast::block b) -> t {
16711671
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
16721672
// doesn't provide type parameter substitutions.
16731673
fn pat_ty(&ctxt cx, &node_type_table ntt, &@ast::pat pat) -> t {
1674-
alt (pat.node) {
1675-
case (ast::pat_wild(?ann)) { ret ann_to_monotype(cx, ntt, ann); }
1676-
case (ast::pat_lit(_, ?ann)) { ret ann_to_monotype(cx, ntt, ann); }
1677-
case (ast::pat_bind(_, _, ?ann)) {
1678-
ret ann_to_monotype(cx, ntt, ann);
1679-
}
1680-
case (ast::pat_tag(_, _, ?ann)) {
1681-
ret ann_to_monotype(cx, ntt, ann);
1682-
}
1683-
}
1684-
fail; // not reached
1674+
ret ann_to_monotype(cx, ntt, pat_ann(pat));
16851675
}
16861676

16871677
fn item_ann(&@ast::item it) -> ast::ann {
@@ -1768,6 +1758,26 @@ fn expr_has_ty_params(&node_type_table ntt, &@ast::expr expr) -> bool {
17681758
ret ann_has_type_params(ntt, expr_ann(expr));
17691759
}
17701760

1761+
fn stmt_ann(&@ast::stmt s) -> ast::ann {
1762+
alt (s.node) {
1763+
case (ast::stmt_decl(_, ?a)) { ret a; }
1764+
case (ast::stmt_expr(_, ?a)) { ret a; }
1765+
case (ast::stmt_crate_directive(_)) {
1766+
log_err "ty::stmt_ann(): crate directive found";
1767+
fail;
1768+
}
1769+
}
1770+
}
1771+
1772+
fn pat_ann(&@ast::pat p) -> ast::ann {
1773+
alt (p.node) {
1774+
case (ast::pat_wild(?a)) { ret a; }
1775+
case (ast::pat_bind(_, _, ?a)) { ret a; }
1776+
case (ast::pat_lit(_, ?a)) { ret a; }
1777+
case (ast::pat_tag(_, _, ?a)) { ret a; }
1778+
}
1779+
}
1780+
17711781

17721782
// Expression utilities
17731783

src/comp/middle/typeck.rs

Lines changed: 72 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,65 +1495,88 @@ mod Pushdown {
14951495
// Local variable resolution: the phase that finds all the types in the AST
14961496
// and replaces opaque "ty_local" types with the resolved local types.
14971497

1498-
fn writeback_local(&option::t[@fn_ctxt] env, &span sp, &@ast::local local)
1499-
-> @ast::decl {
1500-
auto fcx = option::get[@fn_ctxt](env);
1501-
1502-
auto local_ty;
1503-
alt (fcx.locals.find(local.id)) {
1504-
case (none[ty::t]) {
1505-
fcx.ccx.sess.span_err(sp, "unable to determine type of local: "
1506-
+ local.ident);
1507-
fail;
1508-
}
1509-
case (some[ty::t](?lt)) {
1510-
local_ty = lt;
1498+
mod writeback {
1499+
fn wb_local(&@fn_ctxt fcx, &span sp, &@ast::local local) {
1500+
auto local_ty;
1501+
alt (fcx.locals.find(local.id)) {
1502+
case (none[ty::t]) {
1503+
fcx.ccx.sess.span_err(sp,
1504+
"unable to determine type of local: " + local.ident);
1505+
fail;
1506+
}
1507+
case (some[ty::t](?lt)) {
1508+
local_ty = lt;
1509+
}
15111510
}
1512-
}
15131511

1514-
auto local_wb = @rec(ann=triv_ann(local.ann.id, local_ty) with *local);
1515-
write_type_only(fcx.ccx.node_types, local.ann.id, local_ty);
1516-
ret @fold::respan[ast::decl_](sp, ast::decl_local(local_wb));
1517-
}
1512+
write_type_only(fcx.ccx.node_types, local.ann.id, local_ty);
1513+
}
15181514

1519-
fn resolve_local_types_in_annotation(&option::t[@fn_ctxt] env, &ast::ann ann)
1520-
-> ast::ann {
1521-
fn resolver(@fn_ctxt fcx, ty::t typ) -> ty::t {
1522-
alt (struct(fcx.ccx.tcx, typ)) {
1523-
case (ty::ty_local(?lid)) { ret fcx.locals.get(lid); }
1524-
case (_) { ret typ; }
1515+
fn resolve_local_types(&@fn_ctxt fcx, &ast::ann ann) {
1516+
fn resolver(@fn_ctxt fcx, ty::t typ) -> ty::t {
1517+
alt (struct(fcx.ccx.tcx, typ)) {
1518+
case (ty::ty_local(?lid)) { ret fcx.locals.get(lid); }
1519+
case (_) { ret typ; }
1520+
}
15251521
}
1522+
1523+
auto tpot = ty::ann_to_ty_param_substs_opt_and_ty(fcx.ccx.node_types,
1524+
ann);
1525+
auto tt = tpot._1;
1526+
if (!ty::type_contains_locals(fcx.ccx.tcx, tt)) { ret; }
1527+
1528+
auto f = bind resolver(fcx, _);
1529+
auto new_type = ty::fold_ty(fcx.ccx.tcx, f, tt);
1530+
write_type(fcx.ccx.node_types, ann.id, tup(tpot._0, new_type));
15261531
}
15271532

1528-
auto fcx = option::get[@fn_ctxt](env);
1533+
fn visit_stmt_pre(@fn_ctxt fcx, &@ast::stmt s) {
1534+
resolve_local_types(fcx, ty::stmt_ann(s));
1535+
}
15291536

1530-
auto tt = ann_to_type(fcx.ccx.node_types, ann);
1531-
if (!ty::type_contains_locals(fcx.ccx.tcx, tt)) { ret ann; }
1537+
fn visit_expr_pre(@fn_ctxt fcx, &@ast::expr e) {
1538+
resolve_local_types(fcx, ty::expr_ann(e));
1539+
}
15321540

1533-
auto f = bind resolver(fcx, _);
1534-
auto new_type = ty::fold_ty(fcx.ccx.tcx, f,
1535-
ann_to_type(fcx.ccx.node_types, ann));
1536-
write_type(fcx.ccx.node_types, ann.id, tup(ann.tps, new_type));
1537-
ret mk_ann_type(ann.id, new_type, ann.tps);
1538-
}
1541+
fn visit_block_pre(@fn_ctxt fcx, &ast::block b) {
1542+
resolve_local_types(fcx, b.node.a);
1543+
}
15391544

1540-
fn resolve_local_types_in_block(&@fn_ctxt fcx, &ast::block block)
1541-
-> ast::block {
1542-
fn update_env_for_item(&option::t[@fn_ctxt] env, &@ast::item i)
1543-
-> option::t[@fn_ctxt] {
1544-
ret none[@fn_ctxt];
1545+
fn visit_arm_pre(@fn_ctxt fcx, &ast::arm a) {
1546+
// FIXME: Need a visit_pat_pre
1547+
resolve_local_types(fcx, ty::pat_ann(a.pat));
15451548
}
1546-
fn keep_going(&option::t[@fn_ctxt] env) -> bool {
1547-
ret !option::is_none[@fn_ctxt](env);
1549+
1550+
fn visit_decl_pre(@fn_ctxt fcx, &@ast::decl d) {
1551+
alt (d.node) {
1552+
case (ast::decl_local(?l)) { wb_local(fcx, d.span, l); }
1553+
case (ast::decl_item(_)) { /* no annotation */ }
1554+
}
15481555
}
15491556

1550-
auto fld = fold::new_identity_fold[option::t[@fn_ctxt]]();
1551-
fld = @rec(fold_decl_local = writeback_local,
1552-
fold_ann = resolve_local_types_in_annotation,
1553-
update_env_for_item = update_env_for_item,
1554-
keep_going = keep_going
1555-
with *fld);
1556-
ret fold::fold_block[option::t[@fn_ctxt]](some(fcx), fld, block);
1557+
fn resolve_local_types_in_block(&@fn_ctxt fcx, &ast::block block) {
1558+
// A trick to ignore any contained items.
1559+
auto ignore = @mutable false;
1560+
fn visit_item_pre(@mutable bool ignore, &@ast::item item) {
1561+
*ignore = true;
1562+
}
1563+
fn visit_item_post(@mutable bool ignore, &@ast::item item) {
1564+
*ignore = false;
1565+
}
1566+
fn keep_going(@mutable bool ignore) -> bool { ret !*ignore; }
1567+
1568+
auto fld = fold::new_identity_fold[option::t[@fn_ctxt]]();
1569+
auto visit = rec(keep_going=bind keep_going(ignore),
1570+
visit_item_pre=bind visit_item_pre(ignore, _),
1571+
visit_item_post=bind visit_item_post(ignore, _),
1572+
visit_stmt_pre=bind visit_stmt_pre(fcx, _),
1573+
visit_expr_pre=bind visit_expr_pre(fcx, _),
1574+
visit_block_pre=bind visit_block_pre(fcx, _),
1575+
visit_arm_pre=bind visit_arm_pre(fcx, _),
1576+
visit_decl_pre=bind visit_decl_pre(fcx, _)
1577+
with walk::default_visitor());
1578+
walk::walk_block(visit, block);
1579+
}
15571580
}
15581581

15591582

@@ -2699,11 +2722,9 @@ fn check_fn(&@crate_ctxt ccx, &ast::fn_decl decl, ast::proto proto,
26992722
case (_) {}
27002723
}
27012724

2702-
auto block_wb = resolve_local_types_in_block(fcx, block_t);
2725+
writeback::resolve_local_types_in_block(fcx, block_t);
27032726

2704-
auto fn_t = rec(decl=decl,
2705-
proto=proto,
2706-
body=block_wb);
2727+
auto fn_t = rec(decl=decl, proto=proto, body=block_t);
27072728
ret fn_t;
27082729
}
27092730

src/comp/middle/walk.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import std::option;
44
import std::option::some;
55
import std::option::none;
66

7+
// FIXME: Should visit patterns as well.
78
type ast_visitor =
89
rec(fn () -> bool keep_going,
910
fn () -> bool want_crate_directives,

0 commit comments

Comments
 (0)