@@ -11,6 +11,10 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
1111use crate :: { Module , ModuleOrUniformRoot , 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:: * ;
@@ -160,6 +164,22 @@ impl RibKind<'_> {
160164 AssocItemRibKind | ItemRibKind ( ..) | ForwardGenericParamBanRibKind => true ,
161165 }
162166 }
167+
168+ /// This rib forbids referring to labels defined in upwards ribs.
169+ fn is_label_barrier ( self ) -> bool {
170+ match self {
171+ NormalRibKind | MacroDefinition ( ..) => false ,
172+
173+ AssocItemRibKind
174+ | ClosureOrAsyncRibKind
175+ | FnItemRibKind
176+ | ItemRibKind ( ..)
177+ | ConstantItemRibKind ( ..)
178+ | ModuleRibKind ( ..)
179+ | ForwardGenericParamBanRibKind
180+ | ConstParamTyRibKind => true ,
181+ }
182+ }
163183}
164184
165185/// A single local scope.
@@ -706,7 +726,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
706726 // Create a value rib for the function.
707727 self . with_rib ( ValueNS , rib_kind, |this| {
708728 // Create a label rib for the function.
709- this. with_label_rib ( rib_kind , |this| {
729+ this. with_label_rib ( FnItemRibKind , |this| {
710730 let async_node_id = fn_kind. header ( ) . and_then ( |h| h. asyncness . opt_return_id ( ) ) ;
711731
712732 if let FnKind :: Fn ( _, _, _, _, generics, _) = fn_kind {
@@ -1400,21 +1420,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14001420 let ribs = & self . label_ribs [ rib_index + 1 ..] ;
14011421
14021422 for rib in ribs {
1403- match rib. kind {
1404- NormalRibKind | MacroDefinition ( ..) => {
1405- // Nothing to do. Continue.
1406- }
1407-
1408- AssocItemRibKind
1409- | ClosureOrAsyncRibKind
1410- | FnItemRibKind
1411- | ItemRibKind ( ..)
1412- | ConstantItemRibKind ( ..)
1413- | ModuleRibKind ( ..)
1414- | ForwardGenericParamBanRibKind
1415- | ConstParamTyRibKind => {
1416- return false ;
1417- }
1423+ if rib. kind . is_label_barrier ( ) {
1424+ return false ;
14181425 }
14191426 }
14201427
@@ -1693,6 +1700,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
16931700 let mut function_value_rib = Rib :: new ( kind) ;
16941701 let mut function_lifetime_rib = LifetimeRib :: new ( lifetime_kind) ;
16951702 let mut seen_bindings = FxHashMap :: default ( ) ;
1703+ let mut seen_lifetimes = FxHashMap :: default ( ) ;
16961704
16971705 // We also can't shadow bindings from the parent item
16981706 if let AssocItemRibKind = kind {
@@ -1710,23 +1718,47 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
17101718
17111719 // Forbid shadowing lifetime bindings
17121720 for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
1713- seen_bindings. extend ( rib. bindings . iter ( ) . map ( |( ident, _) | ( * ident, ident. span ) ) ) ;
1721+ seen_lifetimes. extend (
1722+ rib. bindings . iter ( ) . map ( |( ident, _) | ( * ident, original_lifetime ( ident. span ) ) ) ,
1723+ ) ;
1724+ }
1725+ for rib in self . label_ribs . iter ( ) . rev ( ) {
1726+ if rib. kind . is_label_barrier ( ) {
1727+ break ;
1728+ }
1729+ seen_lifetimes
1730+ . extend ( rib. bindings . iter ( ) . map ( |( ident, _) | ( * ident, original_label ( ident. span ) ) ) ) ;
17141731 }
17151732
17161733 for param in params {
17171734 let ident = param. ident . normalize_to_macros_2_0 ( ) ;
17181735 debug ! ( "with_generic_param_rib: {}" , param. id) ;
17191736
1720- match seen_bindings. entry ( ident) {
1721- Entry :: Occupied ( entry) => {
1722- let span = * entry. get ( ) ;
1723- let err = ResolutionError :: NameAlreadyUsedInParameterList ( ident. name , span) ;
1724- if !matches ! ( param. kind, GenericParamKind :: Lifetime ) {
1725- self . report_error ( param. ident . span , err) ;
1737+ if let GenericParamKind :: Lifetime = param. kind {
1738+ match seen_lifetimes. entry ( ident) {
1739+ Entry :: Occupied ( entry) => {
1740+ let original = * entry. get ( ) ;
1741+ diagnostics:: signal_shadowing_problem (
1742+ self . r . session ,
1743+ ident. name ,
1744+ original,
1745+ shadower_lifetime ( param. ident . span ) ,
1746+ )
1747+ }
1748+ Entry :: Vacant ( entry) => {
1749+ entry. insert ( original_lifetime_param ( param. ident . span ) ) ;
17261750 }
17271751 }
1728- Entry :: Vacant ( entry) => {
1729- entry. insert ( param. ident . span ) ;
1752+ } else {
1753+ match seen_bindings. entry ( ident) {
1754+ Entry :: Occupied ( entry) => {
1755+ let span = * entry. get ( ) ;
1756+ let err = ResolutionError :: NameAlreadyUsedInParameterList ( ident. name , span) ;
1757+ self . report_error ( param. ident . span , err) ;
1758+ }
1759+ Entry :: Vacant ( entry) => {
1760+ entry. insert ( param. ident . span ) ;
1761+ }
17301762 }
17311763 }
17321764
@@ -2911,8 +2943,35 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
29112943 if label. ident . as_str ( ) . as_bytes ( ) [ 1 ] != b'_' {
29122944 self . diagnostic_metadata . unused_labels . insert ( id, label. ident . span ) ;
29132945 }
2946+
2947+ // Forbid shadowing lifetime bindings
2948+ let ident = label. ident . normalize_to_macro_rules ( ) ;
2949+ for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
2950+ if let Some ( ( orig_ident, _) ) = rib. bindings . get_key_value ( & ident) {
2951+ diagnostics:: signal_shadowing_problem (
2952+ self . r . session ,
2953+ label. ident . name ,
2954+ original_lifetime ( orig_ident. span ) ,
2955+ shadower_label ( label. ident . span ) ,
2956+ )
2957+ }
2958+ }
2959+ for rib in self . label_ribs . iter_mut ( ) . rev ( ) {
2960+ if let Some ( ( orig_ident, _) ) = rib. bindings . get_key_value ( & ident) {
2961+ diagnostics:: signal_shadowing_problem (
2962+ self . r . session ,
2963+ label. ident . name ,
2964+ original_label ( orig_ident. span ) ,
2965+ shadower_label ( label. ident . span ) ,
2966+ )
2967+ }
2968+ if rib. kind . is_label_barrier ( ) {
2969+ rib. bindings . insert ( ident, id) ;
2970+ break ;
2971+ }
2972+ }
2973+
29142974 self . with_label_rib ( NormalRibKind , |this| {
2915- let ident = label. ident . normalize_to_macro_rules ( ) ;
29162975 this. label_ribs . last_mut ( ) . unwrap ( ) . bindings . insert ( ident, id) ;
29172976 f ( this) ;
29182977 } ) ;
0 commit comments