@@ -49,6 +49,7 @@ use rustc::ty;
4949use rustc:: hir:: { Freevar , FreevarMap , TraitCandidate , TraitMap , GlobMap } ;
5050use rustc:: util:: nodemap:: { NodeMap , NodeSet , FxHashMap , FxHashSet } ;
5151
52+ use syntax:: abi:: Abi ;
5253use syntax:: ext:: hygiene:: { Mark , SyntaxContext } ;
5354use syntax:: ast:: { self , FloatTy } ;
5455use syntax:: ast:: { CRATE_NODE_ID , Name , NodeId , Ident , SpannedIdent , IntTy , UintTy } ;
@@ -559,7 +560,14 @@ impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
559560
560561impl < ' a , ' tcx > Visitor < ' tcx > for Resolver < ' a > {
561562 fn visit_item ( & mut self , item : & ' tcx Item ) {
563+ let is_lang_item = item. attrs . iter ( ) . any ( |attr| attr. name ( ) == "lang" ) ;
564+ if is_lang_item {
565+ self . check_unused_type_parameters = false ;
566+ }
567+
562568 self . resolve_item ( item) ;
569+
570+ self . check_unused_type_parameters = true ;
563571 }
564572 fn visit_arm ( & mut self , arm : & ' tcx Arm ) {
565573 self . resolve_arm ( arm) ;
@@ -722,15 +730,35 @@ enum RibKind<'a> {
722730struct Rib < ' a > {
723731 bindings : FxHashMap < Ident , Def > ,
724732 kind : RibKind < ' a > ,
733+ sources : FxHashMap < Ident , ( NodeId , Span ) > ,
734+ used_names : RefCell < FxHashSet < Ident > > ,
725735}
726736
727737impl < ' a > Rib < ' a > {
728738 fn new ( kind : RibKind < ' a > ) -> Rib < ' a > {
729739 Rib {
730740 bindings : FxHashMap ( ) ,
731741 kind : kind,
742+ sources : FxHashMap ( ) ,
743+ used_names : RefCell :: new ( FxHashSet ( ) ) ,
732744 }
733745 }
746+
747+ fn insert ( & mut self , ident : Ident , def : Def ) {
748+ self . bindings . insert ( ident, def) ;
749+ }
750+
751+ fn insert_with_source ( & mut self , ident : Ident , id : NodeId , span : Span , def : Def ) {
752+ self . bindings . insert ( ident, def) ;
753+ self . sources . insert ( ident, ( id, span) ) ;
754+ }
755+
756+ fn get ( & self , ident : Ident ) -> Option < Def > {
757+ self . bindings . get ( & ident) . map ( |def| {
758+ self . used_names . borrow_mut ( ) . insert ( ident) ;
759+ def. clone ( )
760+ } )
761+ }
734762}
735763
736764/// A definition along with the index of the rib it was found on
@@ -1114,6 +1142,10 @@ pub struct Resolver<'a> {
11141142
11151143 // Avoid duplicated errors for "name already defined".
11161144 name_already_seen : FxHashMap < Name , Span > ,
1145+
1146+ // Whether unused type parameters should be warned. Default true,
1147+ // false for intrinsics and lang items.
1148+ check_unused_type_parameters : bool ,
11171149}
11181150
11191151pub struct ResolverArenas < ' a > {
@@ -1289,6 +1321,7 @@ impl<'a> Resolver<'a> {
12891321 macro_exports : Vec :: new ( ) ,
12901322 invocations : invocations,
12911323 name_already_seen : FxHashMap ( ) ,
1324+ check_unused_type_parameters : true ,
12921325 }
12931326 }
12941327
@@ -1394,7 +1427,7 @@ impl<'a> Resolver<'a> {
13941427
13951428 // Walk backwards up the ribs in scope.
13961429 for i in ( 0 .. self . ribs [ ns] . len ( ) ) . rev ( ) {
1397- if let Some ( def) = self . ribs [ ns] [ i] . bindings . get ( & ident) . cloned ( ) {
1430+ if let Some ( def) = self . ribs [ ns] [ i] . get ( ident) {
13981431 // The ident resolves to a type parameter or local variable.
13991432 return Some ( LexicalScopeBinding :: Def ( if let Some ( span) = record_used {
14001433 self . adjust_local_def ( LocalDef { ribs : Some ( ( ns, i) ) , def : def } , span)
@@ -1502,7 +1535,7 @@ impl<'a> Resolver<'a> {
15021535 return None ;
15031536 }
15041537 }
1505- let result = rib. bindings . get ( & ident) . cloned ( ) ;
1538+ let result = rib. get ( ident) ;
15061539 if result. is_some ( ) {
15071540 return result;
15081541 }
@@ -1577,10 +1610,22 @@ impl<'a> Resolver<'a> {
15771610 } ) ;
15781611 }
15791612
1580- ItemKind :: Mod ( _) | ItemKind :: ForeignMod ( _) => {
1613+ ItemKind :: Mod ( _) => {
1614+ self . with_scope ( item. id , |this| {
1615+ visit:: walk_item ( this, item) ;
1616+ } ) ;
1617+ }
1618+
1619+ ItemKind :: ForeignMod ( ref m) => {
1620+ if m. abi == Abi :: RustIntrinsic {
1621+ self . check_unused_type_parameters = false ;
1622+ }
1623+
15811624 self . with_scope ( item. id , |this| {
15821625 visit:: walk_item ( this, item) ;
15831626 } ) ;
1627+
1628+ self . check_unused_type_parameters = true ;
15841629 }
15851630
15861631 ItemKind :: Const ( ..) | ItemKind :: Static ( ..) => {
@@ -1637,7 +1682,7 @@ impl<'a> Resolver<'a> {
16371682 {
16381683 match type_parameters {
16391684 HasTypeParameters ( generics, rib_kind) => {
1640- let mut function_type_rib = Rib :: new ( rib_kind) ;
1685+ let mut type_rib = Rib :: new ( rib_kind) ;
16411686 let mut seen_bindings = FxHashMap ( ) ;
16421687 for type_parameter in & generics. ty_params {
16431688 let name = type_parameter. ident . name ;
@@ -1653,12 +1698,13 @@ impl<'a> Resolver<'a> {
16531698 seen_bindings. entry ( name) . or_insert ( type_parameter. span ) ;
16541699
16551700 // plain insert (no renaming)
1701+ let ident = Ident :: with_empty_ctxt ( name) ;
16561702 let def_id = self . definitions . local_def_id ( type_parameter. id ) ;
16571703 let def = Def :: TyParam ( def_id) ;
1658- function_type_rib . bindings . insert ( Ident :: with_empty_ctxt ( name ) , def) ;
1704+ type_rib . insert_with_source ( ident , type_parameter . id , type_parameter . span , def) ;
16591705 self . record_def ( type_parameter. id , PathResolution :: new ( def) ) ;
16601706 }
1661- self . ribs [ TypeNS ] . push ( function_type_rib ) ;
1707+ self . ribs [ TypeNS ] . push ( type_rib ) ;
16621708 }
16631709
16641710 NoTypeParameters => {
@@ -1669,6 +1715,20 @@ impl<'a> Resolver<'a> {
16691715 f ( self ) ;
16701716
16711717 if let HasTypeParameters ( ..) = type_parameters {
1718+ if self . check_unused_type_parameters {
1719+ let type_rib = self . ribs [ TypeNS ] . last ( ) . unwrap ( ) ;
1720+ for ( & name, & ( id, span) ) in & type_rib. sources {
1721+ if name. to_string ( ) . starts_with ( '_' ) {
1722+ continue ;
1723+ }
1724+ if !type_rib. used_names . borrow ( ) . contains ( & name) {
1725+ self . session . add_lint ( lint:: builtin:: UNUSED_TYPE_PARAMETERS ,
1726+ id, span,
1727+ "unused type parameter" . to_string ( ) ) ;
1728+ }
1729+ }
1730+ }
1731+
16721732 self . ribs [ TypeNS ] . pop ( ) ;
16731733 }
16741734 }
@@ -1784,7 +1844,7 @@ impl<'a> Resolver<'a> {
17841844 let mut self_type_rib = Rib :: new ( NormalRibKind ) ;
17851845
17861846 // plain insert (no renaming, types are not currently hygienic....)
1787- self_type_rib. bindings . insert ( keywords:: SelfType . ident ( ) , self_def) ;
1847+ self_type_rib. insert ( keywords:: SelfType . ident ( ) , self_def) ;
17881848 self . ribs [ TypeNS ] . push ( self_type_rib) ;
17891849 f ( self ) ;
17901850 self . ribs [ TypeNS ] . pop ( ) ;
@@ -2098,7 +2158,7 @@ impl<'a> Resolver<'a> {
20982158 // A completely fresh binding, add to the lists if it's valid.
20992159 if ident. node . name != keywords:: Invalid . name ( ) {
21002160 bindings. insert ( ident. node , outer_pat_id) ;
2101- self . ribs [ ValueNS ] . last_mut ( ) . unwrap ( ) . bindings . insert ( ident. node , def) ;
2161+ self . ribs [ ValueNS ] . last_mut ( ) . unwrap ( ) . insert ( ident. node , def) ;
21022162 }
21032163 }
21042164 }
@@ -2605,7 +2665,7 @@ impl<'a> Resolver<'a> {
26052665 if let Some ( label) = label {
26062666 let def = Def :: Label ( id) ;
26072667 self . with_label_rib ( |this| {
2608- this. label_ribs . last_mut ( ) . unwrap ( ) . bindings . insert ( label. node , def) ;
2668+ this. label_ribs . last_mut ( ) . unwrap ( ) . insert ( label. node , def) ;
26092669 this. visit_block ( block) ;
26102670 } ) ;
26112671 } else {
0 commit comments