diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-03-07 15:13:31 -0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-03-07 18:06:29 -0800 |
| commit | 2bfed908e39f162532be56d9680295bb383ddcf2 (patch) | |
| tree | 8bb5b9cb6d3cfc773dd321eedf07985a962cd2d3 /src/rustc/metadata | |
| parent | c9375fed8d55197a528edb3c3182aaf3b71abe76 (diff) | |
| download | rust-2bfed908e39f162532be56d9680295bb383ddcf2.tar.gz rust-2bfed908e39f162532be56d9680295bb383ddcf2.zip | |
Fix #1941: inlining of items that themselves contain nested items
The fix is to drop nested items from the encoded AST. Nested items may themselves be inlined, but that is an independent question.
Diffstat (limited to 'src/rustc/metadata')
| -rw-r--r-- | src/rustc/metadata/astencode.rs | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs index d3d8593b654..d7215fbfcab 100644 --- a/src/rustc/metadata/astencode.rs +++ b/src/rustc/metadata/astencode.rs @@ -63,7 +63,7 @@ fn encode_inlined_item(ecx: @e::encode_ctxt, let id_range = compute_id_range(ii); ebml_w.wr_tag(c::tag_ast as uint) {|| encode_id_range(ebml_w, id_range); - encode_ast(ebml_w, ii); + encode_ast(ebml_w, simplify_ast(ii)); encode_side_tables_for_ii(ecx, ebml_w, ii); } @@ -326,6 +326,44 @@ fn encode_ast(ebml_w: ebml::writer, item: ast::inlined_item) { } } +// Produces a simplified copy of the AST which does not include things +// that we do not need to or do not want to export. For example, we +// do not include any nested items: if these nested items are to be +// inlined, their AST will be exported separately (this only makes +// sense because, in Rust, nested items are independent except for +// their visibility). +// +// As it happens, trans relies on the fact that we do not export +// nested items, as otherwise it would get confused when translating +// inlined items. +fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { + fn drop_nested_items(blk: ast::blk_, fld: fold::ast_fold) -> ast::blk_ { + let stmts_sans_items = vec::filter(blk.stmts) {|stmt| + alt stmt.node { + ast::stmt_expr(_, _) | ast::stmt_semi(_, _) | + ast::stmt_decl(@{node: ast::decl_local(_), span: _}, _) { true } + ast::stmt_decl(@{node: ast::decl_item(_), span: _}, _) { false } + } + }; + let blk_sans_items = { stmts: stmts_sans_items with blk }; + fold::noop_fold_block(blk_sans_items, fld) + } + + let fld = fold::make_fold({ + fold_block: fold::wrap(drop_nested_items) + with *fold::default_ast_fold() + }); + + alt ii { + ast::ii_item(i) { + ast::ii_item(fld.fold_item(i)) + } + ast::ii_method(d, m) { + ast::ii_method(d, fld.fold_method(m)) + } + } +} + fn decode_ast(par_doc: ebml::doc) -> ast::inlined_item { let chi_doc = par_doc[c::tag_tree]; let d = serialization::mk_ebml_deserializer(chi_doc); @@ -923,3 +961,26 @@ fn test_more() { } }); } + +#[test] +fn test_simplification() { + let ext_cx = mk_ctxt(); + let item_in = ast::ii_item(#ast(item) { + fn new_int_alist<B: copy>() -> alist<int, B> { + fn eq_int(&&a: int, &&b: int) -> bool { a == b } + ret {eq_fn: eq_int, mut data: []}; + } + }); + let item_out = simplify_ast(item_in); + let item_exp = ast::ii_item(#ast(item) { + fn new_int_alist<B: copy>() -> alist<int, B> { + ret {eq_fn: eq_int, mut data: []}; + } + }); + alt (item_out, item_exp) { + (ast::ii_item(item_out), ast::ii_item(item_exp)) { + assert pprust::item_to_str(item_out) == pprust::item_to_str(item_exp); + } + _ { fail; } + } +} \ No newline at end of file |
