about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2018-01-08 13:43:42 -0800
committerAlex Crichton <alex@alexcrichton.com>2018-01-13 16:07:13 -0800
commit0ecaa67e9082b609bd8fd315b6cc41be7e8ee139 (patch)
tree52ec33dd42e044de23a02791ced2315bc1cf56bf
parent5f006cebfc5939195f6df6d1f50f02f079233928 (diff)
downloadrust-0ecaa67e9082b609bd8fd315b6cc41be7e8ee139.tar.gz
rust-0ecaa67e9082b609bd8fd315b6cc41be7e8ee139.zip
rustc: Refactor attribute checking to operate on HIR
This'll enable running queries that could be cached and overall be more amenable
to the query infastructure.
-rw-r--r--src/librustc/hir/check_attr.rs66
-rw-r--r--src/librustc_driver/driver.rs8
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr4
-rw-r--r--src/test/ui/target-feature-wrong.rs2
-rw-r--r--src/test/ui/target-feature-wrong.stderr20
5 files changed, 56 insertions, 44 deletions
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 77927260068..4b528a0fdc7 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -14,11 +14,10 @@
 //! conflicts between multiple such attributes attached to the same
 //! item.
 
-use session::Session;
+use ty::TyCtxt;
 
-use syntax::ast;
-use syntax::visit;
-use syntax::visit::Visitor;
+use hir;
+use hir::intravisit::{self, Visitor, NestedVisitorMap};
 
 #[derive(Copy, Clone, PartialEq)]
 enum Target {
@@ -30,24 +29,26 @@ enum Target {
 }
 
 impl Target {
-    fn from_item(item: &ast::Item) -> Target {
+    fn from_item(item: &hir::Item) -> Target {
         match item.node {
-            ast::ItemKind::Fn(..) => Target::Fn,
-            ast::ItemKind::Struct(..) => Target::Struct,
-            ast::ItemKind::Union(..) => Target::Union,
-            ast::ItemKind::Enum(..) => Target::Enum,
+            hir::ItemFn(..) => Target::Fn,
+            hir::ItemStruct(..) => Target::Struct,
+            hir::ItemUnion(..) => Target::Union,
+            hir::ItemEnum(..) => Target::Enum,
             _ => Target::Other,
         }
     }
 }
 
-struct CheckAttrVisitor<'a> {
-    sess: &'a Session,
+struct CheckAttrVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
-impl<'a> CheckAttrVisitor<'a> {
+impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
     /// Check any attribute.
-    fn check_attributes(&self, item: &ast::Item, target: Target) {
+    fn check_attributes(&self, item: &hir::Item, target: Target) {
+        self.tcx.target_features_enabled(self.tcx.hir.local_def_id(item.id));
+
         for attr in &item.attrs {
             if let Some(name) = attr.name() {
                 if name == "inline" {
@@ -55,20 +56,24 @@ impl<'a> CheckAttrVisitor<'a> {
                 }
             }
         }
+
         self.check_repr(item, target);
     }
 
     /// Check if an `#[inline]` is applied to a function.
-    fn check_inline(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) {
+    fn check_inline(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
         if target != Target::Fn {
-            struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function")
+            struct_span_err!(self.tcx.sess,
+                             attr.span,
+                             E0518,
+                             "attribute should be applied to function")
                 .span_label(item.span, "not a function")
                 .emit();
         }
     }
 
     /// Check if the `#[repr]` attributes on `item` are valid.
-    fn check_repr(&self, item: &ast::Item, target: Target) {
+    fn check_repr(&self, item: &hir::Item, target: Target) {
         // Extract the names of all repr hints, e.g., [foo, bar, align] for:
         // ```
         // #[repr(foo)]
@@ -144,7 +149,7 @@ impl<'a> CheckAttrVisitor<'a> {
                 }
                 _ => continue,
             };
-            struct_span_err!(self.sess, hint.span, E0517,
+            struct_span_err!(self.tcx.sess, hint.span, E0517,
                              "attribute should be applied to {}", allowed_targets)
                 .span_label(item.span, format!("not {} {}", article, allowed_targets))
                 .emit();
@@ -154,32 +159,37 @@ impl<'a> CheckAttrVisitor<'a> {
         if (int_reprs > 1)
            || (is_simd && is_c)
            || (int_reprs == 1 && is_c && is_c_like_enum(item)) {
-            // Just point at all repr hints. This is not ideal, but tracking precisely which ones
-            // are at fault is a huge hassle.
+            // Just point at all repr hints. This is not ideal, but tracking
+            // precisely which ones are at fault is a huge hassle.
             let spans: Vec<_> = hints.iter().map(|hint| hint.span).collect();
-            span_warn!(self.sess, spans, E0566,
+            span_warn!(self.tcx.sess, spans, E0566,
                        "conflicting representation hints");
         }
     }
 }
 
-impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
-    fn visit_item(&mut self, item: &'a ast::Item) {
+impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
         let target = Target::from_item(item);
         self.check_attributes(item, target);
-        visit::walk_item(self, item);
+        intravisit::walk_item(self, item);
     }
 }
 
-pub fn check_crate(sess: &Session, krate: &ast::Crate) {
-    visit::walk_crate(&mut CheckAttrVisitor { sess: sess }, krate);
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    let mut checker = CheckAttrVisitor { tcx };
+    tcx.hir.krate().visit_all_item_likes(&mut checker.as_deep_visitor());
 }
 
-fn is_c_like_enum(item: &ast::Item) -> bool {
-    if let ast::ItemKind::Enum(ref def, _) = item.node {
+fn is_c_like_enum(item: &hir::Item) -> bool {
+    if let hir::ItemEnum(ref def, _) = item.node {
         for variant in &def.variants {
             match variant.node.data {
-                ast::VariantData::Unit(_) => { /* continue */ }
+                hir::VariantData::Unit(_) => { /* continue */ }
                 _ => { return false; }
             }
         }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index b7265762208..73c1b698087 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -210,10 +210,6 @@ pub fn compile_input(sess: &Session,
                                     Ok(()));
         }
 
-        time(sess.time_passes(), "attribute checking", || {
-            hir::check_attr::check_crate(sess, &expanded_crate);
-        });
-
         let opt_crate = if control.keep_ast {
             Some(&expanded_crate)
         } else {
@@ -1038,6 +1034,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
         // tcx available.
         rustc_incremental::dep_graph_tcx_init(tcx);
 
+        time(sess.time_passes(), "attribute checking", || {
+            hir::check_attr::check_crate(tcx)
+        });
+
         time(time_passes,
              "stability checking",
              || stability::check_unstable_api_usage(tcx));
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
index 92bda4d0446..444c4176994 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
@@ -1,3 +1,5 @@
+error[E0601]: main function not found
+
 error[E0518]: attribute should be applied to function
   --> $DIR/issue-43106-gating-of-inline.rs:21:1
    |
@@ -37,7 +39,5 @@ error[E0518]: attribute should be applied to function
 35 |     #[inline = "2100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^ ---------- not a function
 
-error[E0601]: main function not found
-
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/target-feature-wrong.rs b/src/test/ui/target-feature-wrong.rs
index df24035e10b..e70d549ed57 100644
--- a/src/test/ui/target-feature-wrong.rs
+++ b/src/test/ui/target-feature-wrong.rs
@@ -10,6 +10,8 @@
 
 // ignore-arm
 // ignore-aarch64
+// ignore-wasm
+// ignore-emscripten
 
 #![feature(target_feature)]
 
diff --git a/src/test/ui/target-feature-wrong.stderr b/src/test/ui/target-feature-wrong.stderr
index 0cbfeb3a7b7..c5534bf147d 100644
--- a/src/test/ui/target-feature-wrong.stderr
+++ b/src/test/ui/target-feature-wrong.stderr
@@ -1,31 +1,31 @@
 warning: #[target_feature = ".."] is deprecated and will eventually be removed, use #[target_feature(enable = "..")] instead
-  --> $DIR/target-feature-wrong.rs:16:1
+  --> $DIR/target-feature-wrong.rs:18:1
    |
-16 | #[target_feature = "+sse2"]
+18 | #[target_feature = "+sse2"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the feature named `foo` is not valid for this target
-  --> $DIR/target-feature-wrong.rs:18:18
+  --> $DIR/target-feature-wrong.rs:20:18
    |
-18 | #[target_feature(enable = "foo")]
+20 | #[target_feature(enable = "foo")]
    |                  ^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:20:18
+  --> $DIR/target-feature-wrong.rs:22:18
    |
-20 | #[target_feature(bar)]
+22 | #[target_feature(bar)]
    |                  ^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:22:18
+  --> $DIR/target-feature-wrong.rs:24:18
    |
-22 | #[target_feature(disable = "baz")]
+24 | #[target_feature(disable = "baz")]
    |                  ^^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] can only be applied to `unsafe` function
-  --> $DIR/target-feature-wrong.rs:26:1
+  --> $DIR/target-feature-wrong.rs:28:1
    |
-26 | #[target_feature(enable = "sse2")]
+28 | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors