@@ -172,6 +172,23 @@ impl RibKind<'_> {
172
172
AssocItemRibKind | ItemRibKind ( _) | ForwardGenericParamBanRibKind => true ,
173
173
}
174
174
}
175
+
176
+ /// This rib forbids referring to labels defined in upwards ribs.
177
+ fn is_label_barrier ( self ) -> bool {
178
+ match self {
179
+ NormalRibKind | MacroDefinition ( ..) => false ,
180
+
181
+ AssocItemRibKind
182
+ | ClosureOrAsyncRibKind
183
+ | FnItemRibKind
184
+ | ItemRibKind ( ..)
185
+ | ConstantItemRibKind ( ..)
186
+ | ModuleRibKind ( ..)
187
+ | ForwardGenericParamBanRibKind
188
+ | ConstParamTyRibKind
189
+ | InlineAsmSymRibKind => true ,
190
+ }
191
+ }
175
192
}
176
193
177
194
/// A single local scope.
@@ -732,7 +749,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
732
749
// Create a value rib for the function.
733
750
self . with_rib ( ValueNS , rib_kind, |this| {
734
751
// Create a label rib for the function.
735
- this. with_label_rib ( rib_kind , |this| {
752
+ this. with_label_rib ( FnItemRibKind , |this| {
736
753
let async_node_id = fn_kind. header ( ) . and_then ( |h| h. asyncness . opt_return_id ( ) ) ;
737
754
738
755
if let FnKind :: Fn ( _, _, _, _, generics, _) = fn_kind {
@@ -1531,13 +1548,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1531
1548
1532
1549
/// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved
1533
1550
/// label and reports an error if the label is not found or is unreachable.
1534
- fn resolve_label ( & mut self , mut label : Ident ) -> Option < NodeId > {
1551
+ fn resolve_label ( & mut self , mut label : Ident ) -> Result < ( NodeId , Span ) , ResolutionError < ' a > > {
1535
1552
let mut suggestion = None ;
1536
1553
1537
- // Preserve the original span so that errors contain "in this macro invocation"
1538
- // information.
1539
- let original_span = label. span ;
1540
-
1541
1554
for i in ( 0 ..self . label_ribs . len ( ) ) . rev ( ) {
1542
1555
let rib = & self . label_ribs [ i] ;
1543
1556
@@ -1553,18 +1566,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1553
1566
if let Some ( ( ident, id) ) = rib. bindings . get_key_value ( & ident) {
1554
1567
let definition_span = ident. span ;
1555
1568
return if self . is_label_valid_from_rib ( i) {
1556
- Some ( * id)
1569
+ Ok ( ( * id, definition_span ) )
1557
1570
} else {
1558
- self . report_error (
1559
- original_span,
1560
- ResolutionError :: UnreachableLabel {
1561
- name : label. name ,
1562
- definition_span,
1563
- suggestion,
1564
- } ,
1565
- ) ;
1566
-
1567
- None
1571
+ Err ( ResolutionError :: UnreachableLabel {
1572
+ name : label. name ,
1573
+ definition_span,
1574
+ suggestion,
1575
+ } )
1568
1576
} ;
1569
1577
}
1570
1578
@@ -1573,34 +1581,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1573
1581
suggestion = suggestion. or_else ( || self . suggestion_for_label_in_rib ( i, label) ) ;
1574
1582
}
1575
1583
1576
- self . report_error (
1577
- original_span,
1578
- ResolutionError :: UndeclaredLabel { name : label. name , suggestion } ,
1579
- ) ;
1580
- None
1584
+ Err ( ResolutionError :: UndeclaredLabel { name : label. name , suggestion } )
1581
1585
}
1582
1586
1583
1587
/// Determine whether or not a label from the `rib_index`th label rib is reachable.
1584
1588
fn is_label_valid_from_rib ( & self , rib_index : usize ) -> bool {
1585
1589
let ribs = & self . label_ribs [ rib_index + 1 ..] ;
1586
1590
1587
1591
for rib in ribs {
1588
- match rib. kind {
1589
- NormalRibKind | MacroDefinition ( ..) => {
1590
- // Nothing to do. Continue.
1591
- }
1592
-
1593
- AssocItemRibKind
1594
- | ClosureOrAsyncRibKind
1595
- | FnItemRibKind
1596
- | ItemRibKind ( ..)
1597
- | ConstantItemRibKind ( ..)
1598
- | ModuleRibKind ( ..)
1599
- | ForwardGenericParamBanRibKind
1600
- | ConstParamTyRibKind
1601
- | InlineAsmSymRibKind => {
1602
- return false ;
1603
- }
1592
+ if rib. kind . is_label_barrier ( ) {
1593
+ return false ;
1604
1594
}
1605
1595
}
1606
1596
@@ -1895,6 +1885,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1895
1885
let mut function_value_rib = Rib :: new ( kind) ;
1896
1886
let mut function_lifetime_rib = LifetimeRib :: new ( lifetime_kind) ;
1897
1887
let mut seen_bindings = FxHashMap :: default ( ) ;
1888
+ // Store all seen lifetimes names from outer scopes.
1889
+ let mut seen_lifetimes = FxHashSet :: default ( ) ;
1898
1890
1899
1891
// We also can't shadow bindings from the parent item
1900
1892
if let AssocItemRibKind = kind {
@@ -1910,16 +1902,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1910
1902
add_bindings_for_ns ( TypeNS ) ;
1911
1903
}
1912
1904
1905
+ // Forbid shadowing lifetime bindings
1906
+ for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
1907
+ seen_lifetimes. extend ( rib. bindings . iter ( ) . map ( |( ident, _) | * ident) ) ;
1908
+ if let LifetimeRibKind :: Item = rib. kind {
1909
+ break ;
1910
+ }
1911
+ }
1912
+
1913
1913
for param in params {
1914
1914
let ident = param. ident . normalize_to_macros_2_0 ( ) ;
1915
1915
debug ! ( "with_generic_param_rib: {}" , param. id) ;
1916
1916
1917
+ if let GenericParamKind :: Lifetime = param. kind
1918
+ && let Some ( & original) = seen_lifetimes. get ( & ident)
1919
+ {
1920
+ diagnostics:: signal_lifetime_shadowing ( self . r . session , original, param. ident ) ;
1921
+ // Record lifetime res, so lowering knows there is something fishy.
1922
+ self . record_lifetime_res ( param. id , LifetimeRes :: Error ) ;
1923
+ continue ;
1924
+ }
1925
+
1917
1926
match seen_bindings. entry ( ident) {
1918
1927
Entry :: Occupied ( entry) => {
1919
1928
let span = * entry. get ( ) ;
1920
1929
let err = ResolutionError :: NameAlreadyUsedInParameterList ( ident. name , span) ;
1921
- if !matches ! ( param. kind, GenericParamKind :: Lifetime ) {
1922
- self . report_error ( param. ident . span , err) ;
1930
+ self . report_error ( param. ident . span , err) ;
1931
+ if let GenericParamKind :: Lifetime = param. kind {
1932
+ // Record lifetime res, so lowering knows there is something fishy.
1933
+ self . record_lifetime_res ( param. id , LifetimeRes :: Error ) ;
1934
+ continue ;
1923
1935
}
1924
1936
}
1925
1937
Entry :: Vacant ( entry) => {
@@ -1936,6 +1948,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1936
1948
)
1937
1949
. span_label ( param. ident . span , "`'_` is a reserved lifetime name" )
1938
1950
. emit ( ) ;
1951
+ // Record lifetime res, so lowering knows there is something fishy.
1952
+ self . record_lifetime_res ( param. id , LifetimeRes :: Error ) ;
1939
1953
continue ;
1940
1954
}
1941
1955
@@ -1949,6 +1963,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1949
1963
)
1950
1964
. span_label ( param. ident . span , "'static is a reserved lifetime name" )
1951
1965
. emit ( ) ;
1966
+ // Record lifetime res, so lowering knows there is something fishy.
1967
+ self . record_lifetime_res ( param. id , LifetimeRes :: Error ) ;
1952
1968
continue ;
1953
1969
}
1954
1970
@@ -3114,6 +3130,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
3114
3130
if label. ident . as_str ( ) . as_bytes ( ) [ 1 ] != b'_' {
3115
3131
self . diagnostic_metadata . unused_labels . insert ( id, label. ident . span ) ;
3116
3132
}
3133
+
3134
+ if let Ok ( ( _, orig_span) ) = self . resolve_label ( label. ident ) {
3135
+ diagnostics:: signal_label_shadowing ( self . r . session , orig_span, label. ident )
3136
+ }
3137
+
3117
3138
self . with_label_rib ( NormalRibKind , |this| {
3118
3139
let ident = label. ident . normalize_to_macro_rules ( ) ;
3119
3140
this. label_ribs . last_mut ( ) . unwrap ( ) . bindings . insert ( ident, id) ;
@@ -3219,10 +3240,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
3219
3240
}
3220
3241
3221
3242
ExprKind :: Break ( Some ( label) , _) | ExprKind :: Continue ( Some ( label) ) => {
3222
- if let Some ( node_id) = self . resolve_label ( label. ident ) {
3223
- // Since this res is a label, it is never read.
3224
- self . r . label_res_map . insert ( expr. id , node_id) ;
3225
- self . diagnostic_metadata . unused_labels . remove ( & node_id) ;
3243
+ match self . resolve_label ( label. ident ) {
3244
+ Ok ( ( node_id, _) ) => {
3245
+ // Since this res is a label, it is never read.
3246
+ self . r . label_res_map . insert ( expr. id , node_id) ;
3247
+ self . diagnostic_metadata . unused_labels . remove ( & node_id) ;
3248
+ }
3249
+ Err ( error) => {
3250
+ self . report_error ( label. ident . span , error) ;
3251
+ }
3226
3252
}
3227
3253
3228
3254
// visit `break` argument if any
0 commit comments