about summary refs log tree commit diff
diff options
context:
space:
mode:
authorShotaro Yamada <sinkuu@sinkuu.xyz>2017-11-16 21:10:49 +0900
committerShotaro Yamada <sinkuu@sinkuu.xyz>2017-11-24 13:00:55 +0900
commitd602c2efffafeda612f6192db1a44e113186db3e (patch)
tree19be08aeb2ce0c22d3a505a2b4d873862c6130a9
parentbbd7932a66b56da9a1c7d8cc30dc931922b356c0 (diff)
downloadrust-d602c2efffafeda612f6192db1a44e113186db3e.tar.gz
rust-d602c2efffafeda612f6192db1a44e113186db3e.zip
Visit const expressions in check match
-rw-r--r--src/librustc_const_eval/check_match.rs53
1 files changed, 46 insertions, 7 deletions
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index 98ed8d99fda..bae3cf4db01 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -26,6 +26,7 @@ use rustc::lint;
 use rustc_errors::DiagnosticBuilder;
 
 use rustc::hir::def::*;
+use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
 use rustc::hir::{self, Pat, PatKind};
 
@@ -48,14 +49,38 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> {
 
         let def_id = self.tcx.hir.local_def_id(id);
 
-        MatchVisitor {
-            tcx: self.tcx,
-            tables: self.tcx.body_tables(b),
-            region_scope_tree: &self.tcx.region_scope_tree(def_id),
-            param_env: self.tcx.param_env(def_id),
-            identity_substs: Substs::identity_for_item(self.tcx, def_id),
-        }.visit_body(self.tcx.hir.body(b));
+        check_body(self.tcx, def_id, b);
     }
+
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
+        intravisit::walk_item(self, item);
+        match item.node {
+            hir::ItemStatic(.., body_id) | hir::ItemConst(.., body_id) => {
+                let def_id = self.tcx.hir.local_def_id(item.id);
+                check_body(self.tcx, def_id, body_id);
+            }
+            _ => (),
+        }
+    }
+
+    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
+        intravisit::walk_impl_item(self, ii);
+        if let hir::ImplItemKind::Const(_, body_id) = ii.node {
+            let def_id = self.tcx.hir.local_def_id(ii.id);
+            check_body(self.tcx, def_id, body_id);
+        }
+    }
+
+    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
+        intravisit::walk_trait_item(self, ti);
+        if let hir::TraitItemKind::Const(_, Some(body_id)) = ti.node {
+            let def_id = self.tcx.hir.local_def_id(ti.id);
+            check_body(self.tcx, def_id, body_id);
+        }
+    }
+
+    // Enum variants and types (e.g. `[T; { .. }]`) may have bodies too,
+    // but they are const-evaluated during typeck.
 }
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -63,6 +88,20 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     tcx.sess.abort_if_errors();
 }
 
+pub(crate) fn check_body<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+    body_id: hir::BodyId,
+) {
+    MatchVisitor {
+        tcx,
+        tables: tcx.body_tables(body_id),
+        region_scope_tree: &tcx.region_scope_tree(def_id),
+        param_env: tcx.param_env(def_id),
+        identity_substs: Substs::identity_for_item(tcx, def_id),
+    }.visit_body(tcx.hir.body(body_id));
+}
+
 fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> DiagnosticBuilder<'a> {
     struct_span_err!(sess, sp, E0004, "{}", &error_message)
 }