@@ -11,6 +11,10 @@ use crate::{path_names_to_string, BindingError, Finalize, LexicalScopeBinding};
1111use crate :: { Module , ModuleOrUniformRoot , NameBinding , ParentScope , PathResult } ;
1212use crate :: { ResolutionError , Resolver , Segment , UseError } ;
1313
14+ use diagnostics:: {
15+ original_label, original_lifetime, original_lifetime_param, shadower_label, shadower_lifetime,
16+ } ;
17+
1418use rustc_ast:: ptr:: P ;
1519use rustc_ast:: visit:: { self , AssocCtxt , FnCtxt , FnKind , Visitor } ;
1620use rustc_ast:: * ;
@@ -163,6 +167,23 @@ impl RibKind<'_> {
163167 AssocItemRibKind | ItemRibKind ( _) | ForwardGenericParamBanRibKind => true ,
164168 }
165169 }
170+
171+ /// This rib forbids referring to labels defined in upwards ribs.
172+ fn is_label_barrier ( self ) -> bool {
173+ match self {
174+ NormalRibKind | MacroDefinition ( ..) => false ,
175+
176+ AssocItemRibKind
177+ | ClosureOrAsyncRibKind
178+ | FnItemRibKind
179+ | ItemRibKind ( ..)
180+ | ConstantItemRibKind ( ..)
181+ | ModuleRibKind ( ..)
182+ | ForwardGenericParamBanRibKind
183+ | ConstParamTyRibKind
184+ | InlineAsmSymRibKind => true ,
185+ }
186+ }
166187}
167188
168189/// A single local scope.
@@ -684,7 +705,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
684705 // Create a value rib for the function.
685706 self . with_rib ( ValueNS , rib_kind, |this| {
686707 // Create a label rib for the function.
687- this. with_label_rib ( rib_kind , |this| {
708+ this. with_label_rib ( FnItemRibKind , |this| {
688709 let async_node_id = fn_kind. header ( ) . and_then ( |h| h. asyncness . opt_return_id ( ) ) ;
689710
690711 if let FnKind :: Fn ( _, _, _, _, generics, _) = fn_kind {
@@ -1351,22 +1372,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13511372 let ribs = & self . label_ribs [ rib_index + 1 ..] ;
13521373
13531374 for rib in ribs {
1354- match rib. kind {
1355- NormalRibKind | MacroDefinition ( ..) => {
1356- // Nothing to do. Continue.
1357- }
1358-
1359- AssocItemRibKind
1360- | ClosureOrAsyncRibKind
1361- | FnItemRibKind
1362- | ItemRibKind ( ..)
1363- | ConstantItemRibKind ( ..)
1364- | ModuleRibKind ( ..)
1365- | ForwardGenericParamBanRibKind
1366- | ConstParamTyRibKind
1367- | InlineAsmSymRibKind => {
1368- return false ;
1369- }
1375+ if rib. kind . is_label_barrier ( ) {
1376+ return false ;
13701377 }
13711378 }
13721379
@@ -1644,6 +1651,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
16441651 let mut function_value_rib = Rib :: new ( kind) ;
16451652 let mut function_lifetime_rib = LifetimeRib :: new ( lifetime_kind) ;
16461653 let mut seen_bindings = FxHashMap :: default ( ) ;
1654+ let mut seen_lifetimes = FxHashMap :: default ( ) ;
16471655
16481656 // We also can't shadow bindings from the parent item
16491657 if let AssocItemRibKind = kind {
@@ -1659,20 +1667,52 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
16591667 add_bindings_for_ns ( TypeNS ) ;
16601668 }
16611669
1670+ // Forbid shadowing lifetime bindings
1671+ for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
1672+ seen_lifetimes. extend (
1673+ rib. bindings . iter ( ) . map ( |( ident, _) | ( * ident, original_lifetime ( ident. span ) ) ) ,
1674+ ) ;
1675+ if let LifetimeRibKind :: Item = rib. kind {
1676+ break ;
1677+ }
1678+ }
1679+ for rib in self . label_ribs . iter ( ) . rev ( ) {
1680+ if rib. kind . is_label_barrier ( ) {
1681+ break ;
1682+ }
1683+ seen_lifetimes
1684+ . extend ( rib. bindings . iter ( ) . map ( |( ident, _) | ( * ident, original_label ( ident. span ) ) ) ) ;
1685+ }
1686+
16621687 for param in params {
16631688 let ident = param. ident . normalize_to_macros_2_0 ( ) ;
16641689 debug ! ( "with_generic_param_rib: {}" , param. id) ;
16651690
1666- match seen_bindings. entry ( ident) {
1667- Entry :: Occupied ( entry) => {
1668- let span = * entry. get ( ) ;
1669- let err = ResolutionError :: NameAlreadyUsedInParameterList ( ident. name , span) ;
1670- if !matches ! ( param. kind, GenericParamKind :: Lifetime ) {
1671- self . report_error ( param. ident . span , err) ;
1691+ if let GenericParamKind :: Lifetime = param. kind {
1692+ match seen_lifetimes. entry ( ident) {
1693+ Entry :: Occupied ( entry) => {
1694+ let original = * entry. get ( ) ;
1695+ diagnostics:: signal_shadowing_problem (
1696+ self . r . session ,
1697+ ident. name ,
1698+ original,
1699+ shadower_lifetime ( param. ident . span ) ,
1700+ )
1701+ }
1702+ Entry :: Vacant ( entry) => {
1703+ entry. insert ( original_lifetime_param ( param. ident . span ) ) ;
16721704 }
16731705 }
1674- Entry :: Vacant ( entry) => {
1675- entry. insert ( param. ident . span ) ;
1706+ } else {
1707+ match seen_bindings. entry ( ident) {
1708+ Entry :: Occupied ( entry) => {
1709+ let span = * entry. get ( ) ;
1710+ let err = ResolutionError :: NameAlreadyUsedInParameterList ( ident. name , span) ;
1711+ self . report_error ( param. ident . span , err) ;
1712+ }
1713+ Entry :: Vacant ( entry) => {
1714+ entry. insert ( param. ident . span ) ;
1715+ }
16761716 }
16771717 }
16781718
@@ -2852,8 +2892,35 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
28522892 if label. ident . as_str ( ) . as_bytes ( ) [ 1 ] != b'_' {
28532893 self . diagnostic_metadata . unused_labels . insert ( id, label. ident . span ) ;
28542894 }
2895+
2896+ // Forbid shadowing lifetime bindings
2897+ let ident = label. ident . normalize_to_macro_rules ( ) ;
2898+ for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
2899+ if let Some ( ( orig_ident, _) ) = rib. bindings . get_key_value ( & ident) {
2900+ diagnostics:: signal_shadowing_problem (
2901+ self . r . session ,
2902+ label. ident . name ,
2903+ original_lifetime ( orig_ident. span ) ,
2904+ shadower_label ( label. ident . span ) ,
2905+ )
2906+ }
2907+ }
2908+ for rib in self . label_ribs . iter_mut ( ) . rev ( ) {
2909+ if let Some ( ( orig_ident, _) ) = rib. bindings . get_key_value ( & ident) {
2910+ diagnostics:: signal_shadowing_problem (
2911+ self . r . session ,
2912+ label. ident . name ,
2913+ original_label ( orig_ident. span ) ,
2914+ shadower_label ( label. ident . span ) ,
2915+ )
2916+ }
2917+ if rib. kind . is_label_barrier ( ) {
2918+ rib. bindings . insert ( ident, id) ;
2919+ break ;
2920+ }
2921+ }
2922+
28552923 self . with_label_rib ( NormalRibKind , |this| {
2856- let ident = label. ident . normalize_to_macro_rules ( ) ;
28572924 this. label_ribs . last_mut ( ) . unwrap ( ) . bindings . insert ( ident, id) ;
28582925 f ( this) ;
28592926 } ) ;
0 commit comments