Skip to content

Commit 60a669a

Browse files
committed
auto merge of #18608 : alexcrichton/rust/lint-some-crates, r=aturon
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 r? @aturon
2 parents e84e7a0 + 68ac44c commit 60a669a

File tree

3 files changed

+51
-30
lines changed

3 files changed

+51
-30
lines changed

src/librustc/lint/builtin.rs

+48-27
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use syntax::ast_map;
4545
use syntax::ast_util::is_shift_binop;
4646
use syntax::attr::AttrMetaMethods;
4747
use syntax::attr;
48-
use syntax::codemap::Span;
48+
use syntax::codemap::{Span, DUMMY_SP};
4949
use syntax::parse::token;
5050
use syntax::{ast, ast_util, visit};
5151
use syntax::ast::{TyI, TyU, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
@@ -1553,11 +1553,57 @@ declare_lint!(UNSTABLE, Allow,
15531553
/// `#[unstable]` attributes, or no stability attribute.
15541554
pub struct Stability;
15551555

1556+
impl Stability {
1557+
fn lint(&self, cx: &Context, id: ast::DefId, span: Span) {
1558+
let stability = stability::lookup(cx.tcx, id);
1559+
let cross_crate = !ast_util::is_local(id);
1560+
1561+
// stability attributes are promises made across crates; only
1562+
// check DEPRECATED for crate-local usage.
1563+
let (lint, label) = match stability {
1564+
// no stability attributes == Unstable
1565+
None if cross_crate => (UNSTABLE, "unmarked"),
1566+
Some(attr::Stability { level: attr::Unstable, .. }) if cross_crate =>
1567+
(UNSTABLE, "unstable"),
1568+
Some(attr::Stability { level: attr::Experimental, .. }) if cross_crate =>
1569+
(EXPERIMENTAL, "experimental"),
1570+
Some(attr::Stability { level: attr::Deprecated, .. }) =>
1571+
(DEPRECATED, "deprecated"),
1572+
_ => return
1573+
};
1574+
1575+
let msg = match stability {
1576+
Some(attr::Stability { text: Some(ref s), .. }) => {
1577+
format!("use of {} item: {}", label, *s)
1578+
}
1579+
_ => format!("use of {} item", label)
1580+
};
1581+
1582+
cx.span_lint(lint, span, msg.as_slice());
1583+
}
1584+
}
1585+
15561586
impl LintPass for Stability {
15571587
fn get_lints(&self) -> LintArray {
15581588
lint_array!(DEPRECATED, EXPERIMENTAL, UNSTABLE)
15591589
}
15601590

1591+
fn check_view_item(&mut self, cx: &Context, item: &ast::ViewItem) {
1592+
// compiler-generated `extern crate` statements have a dummy span.
1593+
if item.span == DUMMY_SP { return }
1594+
1595+
let id = match item.node {
1596+
ast::ViewItemExternCrate(_, _, id) => id,
1597+
ast::ViewItemUse(..) => return,
1598+
};
1599+
let cnum = match cx.tcx.sess.cstore.find_extern_mod_stmt_cnum(id) {
1600+
Some(cnum) => cnum,
1601+
None => return,
1602+
};
1603+
let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID };
1604+
self.lint(cx, id, item.span);
1605+
}
1606+
15611607
fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
15621608
// first, check if the given expression was generated by a macro or not
15631609
// we need to go back the expn_info tree to check only the arguments
@@ -1629,32 +1675,7 @@ impl LintPass for Stability {
16291675
}
16301676
_ => return
16311677
};
1632-
1633-
let stability = stability::lookup(cx.tcx, id);
1634-
let cross_crate = !ast_util::is_local(id);
1635-
1636-
// stability attributes are promises made across crates; only
1637-
// check DEPRECATED for crate-local usage.
1638-
let (lint, label) = match stability {
1639-
// no stability attributes == Unstable
1640-
None if cross_crate => (UNSTABLE, "unmarked"),
1641-
Some(attr::Stability { level: attr::Unstable, .. }) if cross_crate =>
1642-
(UNSTABLE, "unstable"),
1643-
Some(attr::Stability { level: attr::Experimental, .. }) if cross_crate =>
1644-
(EXPERIMENTAL, "experimental"),
1645-
Some(attr::Stability { level: attr::Deprecated, .. }) =>
1646-
(DEPRECATED, "deprecated"),
1647-
_ => return
1648-
};
1649-
1650-
let msg = match stability {
1651-
Some(attr::Stability { text: Some(ref s), .. }) => {
1652-
format!("use of {} item: {}", label, *s)
1653-
}
1654-
_ => format!("use of {} item", label)
1655-
};
1656-
1657-
cx.span_lint(lint, span, msg.as_slice());
1678+
self.lint(cx, id, span);
16581679
}
16591680
}
16601681

src/test/compile-fail/lint-output-format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// compile-flags:-F experimental -D unstable
1212
// aux-build:lint_output_format.rs
1313

14-
extern crate lint_output_format;
14+
extern crate lint_output_format; //~ ERROR: use of unmarked item
1515
use lint_output_format::{foo, bar, baz};
1616

1717
fn main() {

src/test/compile-fail/lint-stability.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
mod cross_crate {
2121
#[phase(plugin, link)]
22-
extern crate lint_stability;
22+
extern crate lint_stability; //~ ERROR: use of unmarked item
2323
use self::lint_stability::*;
2424

2525
fn test() {
@@ -144,7 +144,7 @@ mod cross_crate {
144144
}
145145

146146
mod inheritance {
147-
extern crate inherited_stability;
147+
extern crate inherited_stability; //~ ERROR: use of experimental item
148148
use self::inherited_stability::*;
149149

150150
fn test_inheritance() {

0 commit comments

Comments
 (0)