1212use driver:: session;
1313use middle:: ty;
1414use middle:: pat_util;
15+ use metadata:: csearch;
1516use util:: ppaux:: { ty_to_str} ;
1617
1718use std:: cmp;
@@ -27,7 +28,7 @@ use std::u8;
2728use extra:: smallintmap:: SmallIntMap ;
2829use syntax:: ast_map;
2930use syntax:: attr;
30- use syntax:: attr:: AttrMetaMethods ;
31+ use syntax:: attr:: { AttrMetaMethods , AttributeMethods } ;
3132use syntax:: codemap:: Span ;
3233use syntax:: codemap;
3334use syntax:: parse:: token;
@@ -97,6 +98,10 @@ pub enum lint {
9798 missing_doc,
9899 unreachable_code,
99100
101+ deprecated,
102+ experimental,
103+ unstable,
104+
100105 warnings,
101106}
102107
@@ -281,6 +286,27 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
281286 default : warn
282287 } ) ,
283288
289+ ( "deprecated" ,
290+ LintSpec {
291+ lint : deprecated,
292+ desc : "detects use of #[deprecated] items" ,
293+ default : warn
294+ } ) ,
295+
296+ ( "experimental" ,
297+ LintSpec {
298+ lint : experimental,
299+ desc : "detects use of #[experimental] items" ,
300+ default : warn
301+ } ) ,
302+
303+ ( "unstable" ,
304+ LintSpec {
305+ lint : unstable,
306+ desc : "detects use of #[unstable] items (incl. items with no stability attribute)" ,
307+ default : allow
308+ } ) ,
309+
284310 ( "warnings" ,
285311 LintSpec {
286312 lint : warnings,
@@ -1375,6 +1401,107 @@ fn lint_missing_doc() -> @mut OuterLint {
13751401 @mut MissingDocLintVisitor { stopping_on_items : false } as @mut OuterLint
13761402}
13771403
1404+ /// Checks for use of items with #[deprecated], #[experimental] and
1405+ /// #[unstable] (or none of them) attributes.
1406+ struct StabilityLintVisitor { stopping_on_items : bool }
1407+
1408+ impl StabilityLintVisitor {
1409+ fn handle_def ( & mut self , sp : Span , def : & ast:: Def , cx : @mut Context ) {
1410+ let id = ast_util:: def_id_of_def ( * def) ;
1411+
1412+ let stability = if ast_util:: is_local ( id) {
1413+ // this crate
1414+ match cx. tcx . items . find ( & id. node ) {
1415+ Some ( ast_node) => {
1416+ let s = do ast_node. with_attrs |attrs| {
1417+ do attrs. map_move |a| {
1418+ attr:: find_stability ( a. iter ( ) . map ( |a| a. meta ( ) ) )
1419+ }
1420+ } ;
1421+ match s {
1422+ Some ( s) => s,
1423+
1424+ // no possibility of having attributes
1425+ // (e.g. it's a local variable), so just
1426+ // ignore it.
1427+ None => return
1428+ }
1429+ }
1430+ _ => cx. tcx . sess . bug ( fmt ! ( "handle_def: %? not found" , id) )
1431+ }
1432+ } else {
1433+ // cross-crate
1434+
1435+ let mut s = None ;
1436+ // run through all the attributes and take the first
1437+ // stability one.
1438+ do csearch:: get_item_attrs ( cx. tcx . cstore , id) |meta_items| {
1439+ if s. is_none ( ) {
1440+ s = attr:: find_stability ( meta_items. move_iter ( ) )
1441+ }
1442+ }
1443+ s
1444+ } ;
1445+
1446+ let ( lint, label) = match stability {
1447+ // no stability attributes == Unstable
1448+ None => ( unstable, "unmarked" ) ,
1449+ Some ( attr:: Stability { level : attr:: Unstable , _ } ) => ( unstable, "unstable" ) ,
1450+ Some ( attr:: Stability { level : attr:: Experimental , _ } ) => {
1451+ ( experimental, "experimental" )
1452+ }
1453+ Some ( attr:: Stability { level : attr:: Deprecated , _ } ) => ( deprecated, "deprecated" ) ,
1454+ _ => return
1455+ } ;
1456+
1457+ let msg = match stability {
1458+ Some ( attr:: Stability { text : Some ( ref s) , _ } ) => {
1459+ fmt ! ( "use of %s item: %s" , label, * s)
1460+ }
1461+ _ => fmt ! ( "use of %s item" , label)
1462+ } ;
1463+
1464+ cx. span_lint ( lint, sp, msg) ;
1465+ }
1466+ }
1467+
1468+ impl SubitemStoppableVisitor for StabilityLintVisitor {
1469+ fn is_running_on_items ( & mut self ) -> bool { !self . stopping_on_items }
1470+ }
1471+
1472+ impl Visitor < @mut Context > for StabilityLintVisitor {
1473+ fn visit_item ( & mut self , i : @ast:: item , e : @mut Context ) {
1474+ self . OVERRIDE_visit_item ( i, e) ;
1475+ }
1476+
1477+ fn visit_fn ( & mut self , fk : & visit:: fn_kind , fd : & ast:: fn_decl ,
1478+ b : & ast:: Block , s : Span , n : ast:: NodeId , e : @mut Context ) {
1479+ self . OVERRIDE_visit_fn ( fk, fd, b, s, n, e) ;
1480+ }
1481+
1482+ fn visit_expr ( & mut self , ex : @ast:: Expr , cx : @mut Context ) {
1483+ match ex. node {
1484+ ast:: ExprMethodCall ( * ) |
1485+ ast:: ExprPath ( * ) |
1486+ ast:: ExprStruct ( * ) => {
1487+ match cx. tcx . def_map . find ( & ex. id ) {
1488+ Some ( def) => self . handle_def ( ex. span , def, cx) ,
1489+ None => { }
1490+ }
1491+ }
1492+ _ => { }
1493+ }
1494+
1495+ visit:: walk_expr ( self , ex, cx)
1496+ }
1497+ }
1498+
1499+ outer_lint_boilerplate_impl ! ( StabilityLintVisitor )
1500+
1501+ fn lint_stability ( ) -> @mut OuterLint {
1502+ @mut StabilityLintVisitor { stopping_on_items : false } as @mut OuterLint
1503+ }
1504+
13781505struct LintCheckVisitor ;
13791506
13801507impl Visitor < @mut Context > for LintCheckVisitor {
@@ -1458,6 +1585,7 @@ pub fn check_crate(tcx: ty::ctxt, crate: @ast::Crate) {
14581585 cx. add_old_lint ( lint_unused_mut ( ) ) ;
14591586 cx. add_old_lint ( lint_unnecessary_allocations ( ) ) ;
14601587 cx. add_old_lint ( lint_missing_doc ( ) ) ;
1588+ cx. add_old_lint ( lint_stability ( ) ) ;
14611589 cx. add_lint ( lint_session ( cx) ) ;
14621590
14631591 // Actually perform the lint checks (iterating the ast)
0 commit comments