]> git.lizzy.rs Git - rust.git/commitdiff
process trait/impl items directly from the visitor callback
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 11 Jan 2017 20:46:11 +0000 (15:46 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 25 Jan 2017 20:50:47 +0000 (15:50 -0500)
The current setup processes impl/trait items while visiting
the impl/trait. This means we basically have this setup:

    <Lots> -> TypeckItemBody(Impl) -> Tables(ImplItem{0,1,2,3})

But this was largely an artifact of the older code. By moving the
processing of items into method dedicated for their use, we produce this
setup:

    <Little> -> TypeckItemBody(ImplItem0) -> Tables(ImplItem0)
    ...
    <Little> -> TypeckItemBody(ImplItem3) -> Tables(ImplItem3)

src/librustc_typeck/check/mod.rs
src/test/compile-fail/dep_graph_crosscontaminate_tables.rs [new file with mode: 0644]

index e240c70aaa3a56baf77c2959f0dd7e319d1504b0..02f5d77f249ceac091fb0df79de580b3ca0937e6 100644 (file)
@@ -570,16 +570,43 @@ fn visit_expr(&mut self, e: &'tcx hir::Expr) {
 }
 
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &'tcx hir::Item) {
-        check_item_body(self.ccx, i);
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
+        match item.node {
+            hir::ItemFn(ref decl, .., body_id) => {
+                check_bare_fn(self.ccx, &decl, body_id, item.id, item.span);
+            }
+            _ => { }
+        }
     }
 
-    fn visit_trait_item(&mut self, _item: &'tcx hir::TraitItem) {
-        // done as part of `visit_item` above
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        match trait_item.node {
+            hir::TraitItemKind::Const(_, Some(expr)) => {
+                check_const(self.ccx, expr, trait_item.id)
+            }
+            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body_id)) => {
+                check_bare_fn(self.ccx, &sig.decl, body_id, trait_item.id, trait_item.span);
+            }
+            hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) |
+            hir::TraitItemKind::Const(_, None) |
+            hir::TraitItemKind::Type(..) => {
+                // Nothing to do.
+            }
+        }
     }
 
-    fn visit_impl_item(&mut self, _item: &'tcx hir::ImplItem) {
-        // done as part of `visit_item` above
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+        match impl_item.node {
+            hir::ImplItemKind::Const(_, expr) => {
+                check_const(self.ccx, expr, impl_item.id)
+            }
+            hir::ImplItemKind::Method(ref sig, body_id) => {
+                check_bare_fn(self.ccx, &sig.decl, body_id, impl_item.id, impl_item.span);
+            }
+            hir::ImplItemKind::Type(_) => {
+                // Nothing to do here.
+            }
+        }
     }
 }
 
@@ -897,55 +924,6 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
     }
 }
 
-pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
-    debug!("check_item_body(it.id={}, it.name={})",
-           it.id,
-           ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(it.id)));
-    let _indenter = indenter();
-    match it.node {
-      hir::ItemFn(ref decl, .., body_id) => {
-        check_bare_fn(ccx, &decl, body_id, it.id, it.span);
-      }
-      hir::ItemImpl(.., ref impl_item_refs) => {
-        debug!("ItemImpl {} with id {}", it.name, it.id);
-
-        for impl_item_ref in impl_item_refs {
-            let impl_item = ccx.tcx.map.impl_item(impl_item_ref.id);
-            match impl_item.node {
-                hir::ImplItemKind::Const(_, expr) => {
-                    check_const(ccx, expr, impl_item.id)
-                }
-                hir::ImplItemKind::Method(ref sig, body_id) => {
-                    check_bare_fn(ccx, &sig.decl, body_id, impl_item.id, impl_item.span);
-                }
-                hir::ImplItemKind::Type(_) => {
-                    // Nothing to do here.
-                }
-            }
-        }
-      }
-      hir::ItemTrait(.., ref trait_item_refs) => {
-        for trait_item_ref in trait_item_refs {
-            let trait_item = ccx.tcx.map.trait_item(trait_item_ref.id);
-            match trait_item.node {
-                hir::TraitItemKind::Const(_, Some(expr)) => {
-                    check_const(ccx, expr, trait_item.id)
-                }
-                hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body_id)) => {
-                    check_bare_fn(ccx, &sig.decl, body_id, trait_item.id, trait_item.span);
-                }
-                hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) |
-                hir::TraitItemKind::Const(_, None) |
-                hir::TraitItemKind::Type(..) => {
-                    // Nothing to do.
-                }
-            }
-        }
-      }
-      _ => {/* nothing to do */ }
-    }
-}
-
 fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     def_id: DefId,
                                     item: &hir::Item) {
diff --git a/src/test/compile-fail/dep_graph_crosscontaminate_tables.rs b/src/test/compile-fail/dep_graph_crosscontaminate_tables.rs
new file mode 100644 (file)
index 0000000..06fea1a
--- /dev/null
@@ -0,0 +1,25 @@
+#![feature(rustc_attrs)]
+
+struct Foo {
+    x: u8
+}
+
+impl Foo {
+    // Changing the item `new`...
+    #[rustc_if_this_changed(HirBody)]
+    fn new() -> Foo {
+        Foo { x: 0 }
+    }
+
+    // ...should not cause us to recompute the tables for `with`!
+    #[rustc_then_this_would_need(Tables)] //~ ERROR no path
+    fn with(x: u8) -> Foo {
+        Foo { x: x }
+    }
+}
+
+fn main() {
+    let f = Foo::new();
+    let g = Foo::with(22);
+    assert_eq!(f.x, g.x - 22);
+}