about summary refs log tree commit diff
path: root/src/rustc/metadata/astencode.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/rustc/metadata/astencode.rs')
-rw-r--r--src/rustc/metadata/astencode.rs63
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