@@ -49,6 +49,7 @@ use rustc::ty;
49
49
use rustc:: hir:: { Freevar , FreevarMap , TraitCandidate , TraitMap , GlobMap } ;
50
50
use rustc:: util:: nodemap:: { NodeMap , NodeSet , FxHashMap , FxHashSet } ;
51
51
52
+ use syntax:: abi:: Abi ;
52
53
use syntax:: ext:: hygiene:: { Mark , SyntaxContext } ;
53
54
use syntax:: ast:: { self , FloatTy } ;
54
55
use syntax:: ast:: { CRATE_NODE_ID , Name , NodeId , Ident , SpannedIdent , IntTy , UintTy } ;
@@ -559,7 +560,14 @@ impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
559
560
560
561
impl < ' a , ' tcx > Visitor < ' tcx > for Resolver < ' a > {
561
562
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
+
562
568
self . resolve_item ( item) ;
569
+
570
+ self . check_unused_type_parameters = true ;
563
571
}
564
572
fn visit_arm ( & mut self , arm : & ' tcx Arm ) {
565
573
self . resolve_arm ( arm) ;
@@ -722,15 +730,35 @@ enum RibKind<'a> {
722
730
struct Rib < ' a > {
723
731
bindings : FxHashMap < Ident , Def > ,
724
732
kind : RibKind < ' a > ,
733
+ sources : FxHashMap < Ident , ( NodeId , Span ) > ,
734
+ used_names : RefCell < FxHashSet < Ident > > ,
725
735
}
726
736
727
737
impl < ' a > Rib < ' a > {
728
738
fn new ( kind : RibKind < ' a > ) -> Rib < ' a > {
729
739
Rib {
730
740
bindings : FxHashMap ( ) ,
731
741
kind : kind,
742
+ sources : FxHashMap ( ) ,
743
+ used_names : RefCell :: new ( FxHashSet ( ) ) ,
732
744
}
733
745
}
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
+ }
734
762
}
735
763
736
764
/// A definition along with the index of the rib it was found on
@@ -1114,6 +1142,10 @@ pub struct Resolver<'a> {
1114
1142
1115
1143
// Avoid duplicated errors for "name already defined".
1116
1144
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 ,
1117
1149
}
1118
1150
1119
1151
pub struct ResolverArenas < ' a > {
@@ -1289,6 +1321,7 @@ impl<'a> Resolver<'a> {
1289
1321
macro_exports : Vec :: new ( ) ,
1290
1322
invocations : invocations,
1291
1323
name_already_seen : FxHashMap ( ) ,
1324
+ check_unused_type_parameters : true ,
1292
1325
}
1293
1326
}
1294
1327
@@ -1394,7 +1427,7 @@ impl<'a> Resolver<'a> {
1394
1427
1395
1428
// Walk backwards up the ribs in scope.
1396
1429
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) {
1398
1431
// The ident resolves to a type parameter or local variable.
1399
1432
return Some ( LexicalScopeBinding :: Def ( if let Some ( span) = record_used {
1400
1433
self . adjust_local_def ( LocalDef { ribs : Some ( ( ns, i) ) , def : def } , span)
@@ -1502,7 +1535,7 @@ impl<'a> Resolver<'a> {
1502
1535
return None ;
1503
1536
}
1504
1537
}
1505
- let result = rib. bindings . get ( & ident) . cloned ( ) ;
1538
+ let result = rib. get ( ident) ;
1506
1539
if result. is_some ( ) {
1507
1540
return result;
1508
1541
}
@@ -1577,10 +1610,22 @@ impl<'a> Resolver<'a> {
1577
1610
} ) ;
1578
1611
}
1579
1612
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
+
1581
1624
self . with_scope ( item. id , |this| {
1582
1625
visit:: walk_item ( this, item) ;
1583
1626
} ) ;
1627
+
1628
+ self . check_unused_type_parameters = true ;
1584
1629
}
1585
1630
1586
1631
ItemKind :: Const ( ..) | ItemKind :: Static ( ..) => {
@@ -1637,7 +1682,7 @@ impl<'a> Resolver<'a> {
1637
1682
{
1638
1683
match type_parameters {
1639
1684
HasTypeParameters ( generics, rib_kind) => {
1640
- let mut function_type_rib = Rib :: new ( rib_kind) ;
1685
+ let mut type_rib = Rib :: new ( rib_kind) ;
1641
1686
let mut seen_bindings = FxHashMap ( ) ;
1642
1687
for type_parameter in & generics. ty_params {
1643
1688
let name = type_parameter. ident . name ;
@@ -1653,12 +1698,13 @@ impl<'a> Resolver<'a> {
1653
1698
seen_bindings. entry ( name) . or_insert ( type_parameter. span ) ;
1654
1699
1655
1700
// plain insert (no renaming)
1701
+ let ident = Ident :: with_empty_ctxt ( name) ;
1656
1702
let def_id = self . definitions . local_def_id ( type_parameter. id ) ;
1657
1703
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) ;
1659
1705
self . record_def ( type_parameter. id , PathResolution :: new ( def) ) ;
1660
1706
}
1661
- self . ribs [ TypeNS ] . push ( function_type_rib ) ;
1707
+ self . ribs [ TypeNS ] . push ( type_rib ) ;
1662
1708
}
1663
1709
1664
1710
NoTypeParameters => {
@@ -1669,6 +1715,20 @@ impl<'a> Resolver<'a> {
1669
1715
f ( self ) ;
1670
1716
1671
1717
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
+
1672
1732
self . ribs [ TypeNS ] . pop ( ) ;
1673
1733
}
1674
1734
}
@@ -1784,7 +1844,7 @@ impl<'a> Resolver<'a> {
1784
1844
let mut self_type_rib = Rib :: new ( NormalRibKind ) ;
1785
1845
1786
1846
// 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) ;
1788
1848
self . ribs [ TypeNS ] . push ( self_type_rib) ;
1789
1849
f ( self ) ;
1790
1850
self . ribs [ TypeNS ] . pop ( ) ;
@@ -2098,7 +2158,7 @@ impl<'a> Resolver<'a> {
2098
2158
// A completely fresh binding, add to the lists if it's valid.
2099
2159
if ident. node . name != keywords:: Invalid . name ( ) {
2100
2160
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) ;
2102
2162
}
2103
2163
}
2104
2164
}
@@ -2605,7 +2665,7 @@ impl<'a> Resolver<'a> {
2605
2665
if let Some ( label) = label {
2606
2666
let def = Def :: Label ( id) ;
2607
2667
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) ;
2609
2669
this. visit_block ( block) ;
2610
2670
} ) ;
2611
2671
} else {
0 commit comments