@@ -12,6 +12,10 @@ use crate::{path_names_to_string, BindingError, Finalize, LexicalScopeBinding};
1212use crate :: { Module , ModuleOrUniformRoot , NameBinding , ParentScope , PathResult } ;
1313use crate :: { ResolutionError , Resolver , Segment , UseError } ;
1414
15+ use diagnostics:: {
16+ original_label, original_lifetime, original_lifetime_param, shadower_label, shadower_lifetime,
17+ } ;
18+
1519use rustc_ast:: ptr:: P ;
1620use rustc_ast:: visit:: { self , AssocCtxt , BoundKind , FnCtxt , FnKind , Visitor } ;
1721use rustc_ast:: * ;
@@ -172,6 +176,23 @@ impl RibKind<'_> {
172176 AssocItemRibKind | ItemRibKind ( _) | ForwardGenericParamBanRibKind => true ,
173177 }
174178 }
179+
180+ /// This rib forbids referring to labels defined in upwards ribs.
181+ fn is_label_barrier ( self ) -> bool {
182+ match self {
183+ NormalRibKind | MacroDefinition ( ..) => false ,
184+
185+ AssocItemRibKind
186+ | ClosureOrAsyncRibKind
187+ | FnItemRibKind
188+ | ItemRibKind ( ..)
189+ | ConstantItemRibKind ( ..)
190+ | ModuleRibKind ( ..)
191+ | ForwardGenericParamBanRibKind
192+ | ConstParamTyRibKind
193+ | InlineAsmSymRibKind => true ,
194+ }
195+ }
175196}
176197
177198/// A single local scope.
@@ -732,7 +753,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
732753 // Create a value rib for the function.
733754 self . with_rib ( ValueNS , rib_kind, |this| {
734755 // Create a label rib for the function.
735- this. with_label_rib ( rib_kind , |this| {
756+ this. with_label_rib ( FnItemRibKind , |this| {
736757 let async_node_id = fn_kind. header ( ) . and_then ( |h| h. asyncness . opt_return_id ( ) ) ;
737758
738759 if let FnKind :: Fn ( _, _, _, _, generics, _) = fn_kind {
@@ -1585,22 +1606,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
15851606 let ribs = & self . label_ribs [ rib_index + 1 ..] ;
15861607
15871608 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- }
1609+ if rib. kind . is_label_barrier ( ) {
1610+ return false ;
16041611 }
16051612 }
16061613
@@ -1895,6 +1902,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
18951902 let mut function_value_rib = Rib :: new ( kind) ;
18961903 let mut function_lifetime_rib = LifetimeRib :: new ( lifetime_kind) ;
18971904 let mut seen_bindings = FxHashMap :: default ( ) ;
1905+ let mut seen_lifetimes = FxHashMap :: default ( ) ;
18981906
18991907 // We also can't shadow bindings from the parent item
19001908 if let AssocItemRibKind = kind {
@@ -1910,20 +1918,52 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
19101918 add_bindings_for_ns ( TypeNS ) ;
19111919 }
19121920
1921+ // Forbid shadowing lifetime bindings
1922+ for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
1923+ seen_lifetimes. extend (
1924+ rib. bindings . iter ( ) . map ( |( ident, _) | ( * ident, original_lifetime ( ident. span ) ) ) ,
1925+ ) ;
1926+ if let LifetimeRibKind :: Item = rib. kind {
1927+ break ;
1928+ }
1929+ }
1930+ for rib in self . label_ribs . iter ( ) . rev ( ) {
1931+ if rib. kind . is_label_barrier ( ) {
1932+ break ;
1933+ }
1934+ seen_lifetimes
1935+ . extend ( rib. bindings . iter ( ) . map ( |( ident, _) | ( * ident, original_label ( ident. span ) ) ) ) ;
1936+ }
1937+
19131938 for param in params {
19141939 let ident = param. ident . normalize_to_macros_2_0 ( ) ;
19151940 debug ! ( "with_generic_param_rib: {}" , param. id) ;
19161941
1917- match seen_bindings. entry ( ident) {
1918- Entry :: Occupied ( entry) => {
1919- let span = * entry. get ( ) ;
1920- let err = ResolutionError :: NameAlreadyUsedInParameterList ( ident. name , span) ;
1921- if !matches ! ( param. kind, GenericParamKind :: Lifetime ) {
1922- self . report_error ( param. ident . span , err) ;
1942+ if let GenericParamKind :: Lifetime = param. kind {
1943+ match seen_lifetimes. entry ( ident) {
1944+ Entry :: Occupied ( entry) => {
1945+ let original = * entry. get ( ) ;
1946+ diagnostics:: signal_shadowing_problem (
1947+ self . r . session ,
1948+ ident. name ,
1949+ original,
1950+ shadower_lifetime ( param. ident . span ) ,
1951+ )
1952+ }
1953+ Entry :: Vacant ( entry) => {
1954+ entry. insert ( original_lifetime_param ( param. ident . span ) ) ;
19231955 }
19241956 }
1925- Entry :: Vacant ( entry) => {
1926- entry. insert ( param. ident . span ) ;
1957+ } else {
1958+ match seen_bindings. entry ( ident) {
1959+ Entry :: Occupied ( entry) => {
1960+ let span = * entry. get ( ) ;
1961+ let err = ResolutionError :: NameAlreadyUsedInParameterList ( ident. name , span) ;
1962+ self . report_error ( param. ident . span , err) ;
1963+ }
1964+ Entry :: Vacant ( entry) => {
1965+ entry. insert ( param. ident . span ) ;
1966+ }
19271967 }
19281968 }
19291969
@@ -3114,8 +3154,35 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
31143154 if label. ident . as_str ( ) . as_bytes ( ) [ 1 ] != b'_' {
31153155 self . diagnostic_metadata . unused_labels . insert ( id, label. ident . span ) ;
31163156 }
3157+
3158+ // Forbid shadowing lifetime bindings
3159+ let ident = label. ident . normalize_to_macro_rules ( ) ;
3160+ for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
3161+ if let Some ( ( orig_ident, _) ) = rib. bindings . get_key_value ( & ident) {
3162+ diagnostics:: signal_shadowing_problem (
3163+ self . r . session ,
3164+ label. ident . name ,
3165+ original_lifetime ( orig_ident. span ) ,
3166+ shadower_label ( label. ident . span ) ,
3167+ )
3168+ }
3169+ }
3170+ for rib in self . label_ribs . iter_mut ( ) . rev ( ) {
3171+ if let Some ( ( orig_ident, _) ) = rib. bindings . get_key_value ( & ident) {
3172+ diagnostics:: signal_shadowing_problem (
3173+ self . r . session ,
3174+ label. ident . name ,
3175+ original_label ( orig_ident. span ) ,
3176+ shadower_label ( label. ident . span ) ,
3177+ )
3178+ }
3179+ if rib. kind . is_label_barrier ( ) {
3180+ rib. bindings . insert ( ident, id) ;
3181+ break ;
3182+ }
3183+ }
3184+
31173185 self . with_label_rib ( NormalRibKind , |this| {
3118- let ident = label. ident . normalize_to_macro_rules ( ) ;
31193186 this. label_ribs . last_mut ( ) . unwrap ( ) . bindings . insert ( ident, id) ;
31203187 f ( this) ;
31213188 } ) ;
0 commit comments