From 68ac44cb97d9f7fd5e552aabb516f61cbb5b6760 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 3 Nov 2014 23:54:12 -0800 Subject: [PATCH] rustc: Support stability attributes on crates 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 | 75 +++++++++++++-------- src/test/compile-fail/lint-output-format.rs | 2 +- src/test/compile-fail/lint-stability.rs | 4 +- 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index a0cc862899c..f084c8caea5 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -45,7 +45,7 @@ use syntax::ast_map; 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 @@ declare_lint!(UNSTABLE, Allow, /// `#[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 @@ impl LintPass for Stability { } _ => 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); } } diff --git a/src/test/compile-fail/lint-output-format.rs b/src/test/compile-fail/lint-output-format.rs index db60002b468..35721ee5b14 100644 --- a/src/test/compile-fail/lint-output-format.rs +++ b/src/test/compile-fail/lint-output-format.rs @@ -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() { diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index fdb0d801164..babf12e97f2 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -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 @@ mod cross_crate { } mod inheritance { - extern crate inherited_stability; + extern crate inherited_stability; //~ ERROR: use of experimental item use self::inherited_stability::*; fn test_inheritance() {