]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Support stability attributes on crates
authorAlex Crichton <alex@alexcrichton.com>
Tue, 4 Nov 2014 07:54:12 +0000 (23:54 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 4 Nov 2014 16:13:09 +0000 (08:13 -0800)
This commit adds support for linting `extern crate` statements for stability
attributes attached to the crate itself. This is likely to be the mechanism used
to deny access to experimental crates that are part of the standard
distribution.

cc #18585

src/librustc/lint/builtin.rs
src/test/compile-fail/lint-output-format.rs
src/test/compile-fail/lint-stability.rs

index a0cc862899c19b642c5e83cb93c2baa08bbf19d1..f084c8caea5437d599606f1a5cabf1cd90663408 100644 (file)
@@ -45,7 +45,7 @@
 use syntax::ast_util::is_shift_binop;
 use syntax::attr::AttrMetaMethods;
 use syntax::attr;
-use syntax::codemap::Span;
+use syntax::codemap::{Span, DUMMY_SP};
 use syntax::parse::token;
 use syntax::{ast, ast_util, visit};
 use syntax::ast::{TyI, TyU, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
@@ -1553,11 +1553,57 @@ fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) {
 /// `#[unstable]` attributes, or no stability attribute.
 pub struct Stability;
 
+impl Stability {
+    fn lint(&self, cx: &Context, id: ast::DefId, span: Span) {
+        let stability = stability::lookup(cx.tcx, id);
+        let cross_crate = !ast_util::is_local(id);
+
+        // stability attributes are promises made across crates; only
+        // check DEPRECATED for crate-local usage.
+        let (lint, label) = match stability {
+            // no stability attributes == Unstable
+            None if cross_crate => (UNSTABLE, "unmarked"),
+            Some(attr::Stability { level: attr::Unstable, .. }) if cross_crate =>
+                (UNSTABLE, "unstable"),
+            Some(attr::Stability { level: attr::Experimental, .. }) if cross_crate =>
+                (EXPERIMENTAL, "experimental"),
+            Some(attr::Stability { level: attr::Deprecated, .. }) =>
+                (DEPRECATED, "deprecated"),
+            _ => return
+        };
+
+        let msg = match stability {
+            Some(attr::Stability { text: Some(ref s), .. }) => {
+                format!("use of {} item: {}", label, *s)
+            }
+            _ => format!("use of {} item", label)
+        };
+
+        cx.span_lint(lint, span, msg.as_slice());
+    }
+}
+
 impl LintPass for Stability {
     fn get_lints(&self) -> LintArray {
         lint_array!(DEPRECATED, EXPERIMENTAL, UNSTABLE)
     }
 
+    fn check_view_item(&mut self, cx: &Context, item: &ast::ViewItem) {
+        // compiler-generated `extern crate` statements have a dummy span.
+        if item.span == DUMMY_SP { return }
+
+        let id = match item.node {
+            ast::ViewItemExternCrate(_, _, id) => id,
+            ast::ViewItemUse(..) => return,
+        };
+        let cnum = match cx.tcx.sess.cstore.find_extern_mod_stmt_cnum(id) {
+            Some(cnum) => cnum,
+            None => return,
+        };
+        let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID };
+        self.lint(cx, id, item.span);
+    }
+
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         // first, check if the given expression was generated by a macro or not
         // we need to go back the expn_info tree to check only the arguments
@@ -1629,32 +1675,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
             }
             _ => return
         };
-
-        let stability = stability::lookup(cx.tcx, id);
-        let cross_crate = !ast_util::is_local(id);
-
-        // stability attributes are promises made across crates; only
-        // check DEPRECATED for crate-local usage.
-        let (lint, label) = match stability {
-            // no stability attributes == Unstable
-            None if cross_crate => (UNSTABLE, "unmarked"),
-            Some(attr::Stability { level: attr::Unstable, .. }) if cross_crate =>
-                (UNSTABLE, "unstable"),
-            Some(attr::Stability { level: attr::Experimental, .. }) if cross_crate =>
-                (EXPERIMENTAL, "experimental"),
-            Some(attr::Stability { level: attr::Deprecated, .. }) =>
-                (DEPRECATED, "deprecated"),
-            _ => return
-        };
-
-        let msg = match stability {
-            Some(attr::Stability { text: Some(ref s), .. }) => {
-                format!("use of {} item: {}", label, *s)
-            }
-            _ => format!("use of {} item", label)
-        };
-
-        cx.span_lint(lint, span, msg.as_slice());
+        self.lint(cx, id, span);
     }
 }
 
index db60002b468e11ae48a3fd358b7777383becd975..35721ee5b148f9cfe6329d609db6edb672f8ce65 100644 (file)
@@ -11,7 +11,7 @@
 // compile-flags:-F experimental -D unstable
 // aux-build:lint_output_format.rs
 
-extern crate lint_output_format;
+extern crate lint_output_format; //~ ERROR: use of unmarked item
 use lint_output_format::{foo, bar, baz};
 
 fn main() {
index fdb0d801164bf39e96e4576c3ceeb778466dee7a..babf12e97f2a9adf88ea6512546667edb7352dad 100644 (file)
@@ -19,7 +19,7 @@
 
 mod cross_crate {
     #[phase(plugin, link)]
-    extern crate lint_stability;
+    extern crate lint_stability; //~ ERROR: use of unmarked item
     use self::lint_stability::*;
 
     fn test() {
@@ -144,7 +144,7 @@ fn test_method_object(foo: &Trait) {
 }
 
 mod inheritance {
-    extern crate inherited_stability;
+    extern crate inherited_stability; //~ ERROR: use of experimental item
     use self::inherited_stability::*;
 
     fn test_inheritance() {