@@ -11,6 +11,10 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
11
11
use crate :: { Module , ModuleOrUniformRoot , ParentScope , PathResult } ;
12
12
use crate :: { ResolutionError , Resolver , Segment , UseError } ;
13
13
14
+ use diagnostics:: {
15
+ original_label, original_lifetime, original_lifetime_param, shadower_label, shadower_lifetime,
16
+ } ;
17
+
14
18
use rustc_ast:: ptr:: P ;
15
19
use rustc_ast:: visit:: { self , AssocCtxt , FnCtxt , FnKind , Visitor } ;
16
20
use rustc_ast:: * ;
@@ -160,6 +164,22 @@ impl RibKind<'_> {
160
164
AssocItemRibKind | ItemRibKind ( ..) | ForwardGenericParamBanRibKind => true ,
161
165
}
162
166
}
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
+ }
163
183
}
164
184
165
185
/// A single local scope.
@@ -706,7 +726,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
706
726
// Create a value rib for the function.
707
727
self . with_rib ( ValueNS , rib_kind, |this| {
708
728
// Create a label rib for the function.
709
- this. with_label_rib ( rib_kind , |this| {
729
+ this. with_label_rib ( FnItemRibKind , |this| {
710
730
let async_node_id = fn_kind. header ( ) . and_then ( |h| h. asyncness . opt_return_id ( ) ) ;
711
731
712
732
if let FnKind :: Fn ( _, _, _, _, generics, _) = fn_kind {
@@ -1400,21 +1420,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1400
1420
let ribs = & self . label_ribs [ rib_index + 1 ..] ;
1401
1421
1402
1422
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 ;
1418
1425
}
1419
1426
}
1420
1427
@@ -1693,6 +1700,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1693
1700
let mut function_value_rib = Rib :: new ( kind) ;
1694
1701
let mut function_lifetime_rib = LifetimeRib :: new ( lifetime_kind) ;
1695
1702
let mut seen_bindings = FxHashMap :: default ( ) ;
1703
+ let mut seen_lifetimes = FxHashMap :: default ( ) ;
1696
1704
1697
1705
// We also can't shadow bindings from the parent item
1698
1706
if let AssocItemRibKind = kind {
@@ -1710,23 +1718,47 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1710
1718
1711
1719
// Forbid shadowing lifetime bindings
1712
1720
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 ) ) ) ) ;
1714
1731
}
1715
1732
1716
1733
for param in params {
1717
1734
let ident = param. ident . normalize_to_macros_2_0 ( ) ;
1718
1735
debug ! ( "with_generic_param_rib: {}" , param. id) ;
1719
1736
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 ) ) ;
1726
1750
}
1727
1751
}
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
+ }
1730
1762
}
1731
1763
}
1732
1764
@@ -2911,8 +2943,35 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
2911
2943
if label. ident . as_str ( ) . as_bytes ( ) [ 1 ] != b'_' {
2912
2944
self . diagnostic_metadata . unused_labels . insert ( id, label. ident . span ) ;
2913
2945
}
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
+
2914
2974
self . with_label_rib ( NormalRibKind , |this| {
2915
- let ident = label. ident . normalize_to_macro_rules ( ) ;
2916
2975
this. label_ribs . last_mut ( ) . unwrap ( ) . bindings . insert ( ident, id) ;
2917
2976
f ( this) ;
2918
2977
} ) ;
0 commit comments