@@ -172,6 +172,23 @@ impl RibKind<'_> {
172172 AssocItemRibKind | ItemRibKind ( _) | ForwardGenericParamBanRibKind => true ,
173173 }
174174 }
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+ }
175192}
176193
177194/// A single local scope.
@@ -732,7 +749,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
732749 // Create a value rib for the function.
733750 self . with_rib ( ValueNS , rib_kind, |this| {
734751 // Create a label rib for the function.
735- this. with_label_rib ( rib_kind , |this| {
752+ this. with_label_rib ( FnItemRibKind , |this| {
736753 let async_node_id = fn_kind. header ( ) . and_then ( |h| h. asyncness . opt_return_id ( ) ) ;
737754
738755 if let FnKind :: Fn ( _, _, _, _, generics, _) = fn_kind {
@@ -1531,13 +1548,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
15311548
15321549 /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved
15331550 /// 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 > > {
15351552 let mut suggestion = None ;
15361553
1537- // Preserve the original span so that errors contain "in this macro invocation"
1538- // information.
1539- let original_span = label. span ;
1540-
15411554 for i in ( 0 ..self . label_ribs . len ( ) ) . rev ( ) {
15421555 let rib = & self . label_ribs [ i] ;
15431556
@@ -1553,18 +1566,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
15531566 if let Some ( ( ident, id) ) = rib. bindings . get_key_value ( & ident) {
15541567 let definition_span = ident. span ;
15551568 return if self . is_label_valid_from_rib ( i) {
1556- Some ( * id)
1569+ Ok ( ( * id, definition_span ) )
15571570 } 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+ } )
15681576 } ;
15691577 }
15701578
@@ -1573,34 +1581,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
15731581 suggestion = suggestion. or_else ( || self . suggestion_for_label_in_rib ( i, label) ) ;
15741582 }
15751583
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 } )
15811585 }
15821586
15831587 /// Determine whether or not a label from the `rib_index`th label rib is reachable.
15841588 fn is_label_valid_from_rib ( & self , rib_index : usize ) -> bool {
15851589 let ribs = & self . label_ribs [ rib_index + 1 ..] ;
15861590
15871591 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 ;
16041594 }
16051595 }
16061596
@@ -1895,6 +1885,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
18951885 let mut function_value_rib = Rib :: new ( kind) ;
18961886 let mut function_lifetime_rib = LifetimeRib :: new ( lifetime_kind) ;
18971887 let mut seen_bindings = FxHashMap :: default ( ) ;
1888+ // Store all seen lifetimes names from outer scopes.
1889+ let mut seen_lifetimes = FxHashSet :: default ( ) ;
18981890
18991891 // We also can't shadow bindings from the parent item
19001892 if let AssocItemRibKind = kind {
@@ -1910,16 +1902,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
19101902 add_bindings_for_ns ( TypeNS ) ;
19111903 }
19121904
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+
19131913 for param in params {
19141914 let ident = param. ident . normalize_to_macros_2_0 ( ) ;
19151915 debug ! ( "with_generic_param_rib: {}" , param. id) ;
19161916
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+
19171926 match seen_bindings. entry ( ident) {
19181927 Entry :: Occupied ( entry) => {
19191928 let span = * entry. get ( ) ;
19201929 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 ;
19231935 }
19241936 }
19251937 Entry :: Vacant ( entry) => {
@@ -1936,6 +1948,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
19361948 )
19371949 . span_label ( param. ident . span , "`'_` is a reserved lifetime name" )
19381950 . emit ( ) ;
1951+ // Record lifetime res, so lowering knows there is something fishy.
1952+ self . record_lifetime_res ( param. id , LifetimeRes :: Error ) ;
19391953 continue ;
19401954 }
19411955
@@ -1949,6 +1963,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
19491963 )
19501964 . span_label ( param. ident . span , "'static is a reserved lifetime name" )
19511965 . emit ( ) ;
1966+ // Record lifetime res, so lowering knows there is something fishy.
1967+ self . record_lifetime_res ( param. id , LifetimeRes :: Error ) ;
19521968 continue ;
19531969 }
19541970
@@ -3114,6 +3130,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
31143130 if label. ident . as_str ( ) . as_bytes ( ) [ 1 ] != b'_' {
31153131 self . diagnostic_metadata . unused_labels . insert ( id, label. ident . span ) ;
31163132 }
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+
31173138 self . with_label_rib ( NormalRibKind , |this| {
31183139 let ident = label. ident . normalize_to_macro_rules ( ) ;
31193140 this. label_ribs . last_mut ( ) . unwrap ( ) . bindings . insert ( ident, id) ;
@@ -3219,10 +3240,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
32193240 }
32203241
32213242 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+ }
32263252 }
32273253
32283254 // visit `break` argument if any
0 commit comments