@@ -40,9 +40,9 @@ use thin_vec::ThinVec;
40
40
use tracing:: { debug, instrument, trace} ;
41
41
42
42
use crate :: {
43
- BindingError , BindingKey , Finalize , LexicalScopeBinding , Module , ModuleOrUniformRoot ,
44
- NameBinding , ParentScope , PathResult , ResolutionError , Resolver , Segment , TyCtxt , UseError ,
45
- Used , errors, path_names_to_string, rustdoc,
43
+ BindingError , BindingKey , Finalize , LexicalScopeBinding , LookaheadItemInBlock , Module ,
44
+ ModuleOrUniformRoot , NameBinding , ParentScope , PathResult , ResolutionError , Resolver , Segment ,
45
+ TyCtxt , UseError , Used , errors, path_names_to_string, rustdoc,
46
46
} ;
47
47
48
48
mod diagnostics;
@@ -103,7 +103,7 @@ impl IntoDiagArg for PatternSource {
103
103
/// Denotes whether the context for the set of already bound bindings is a `Product`
104
104
/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
105
105
/// See those functions for more information.
106
- #[ derive( PartialEq ) ]
106
+ #[ derive( PartialEq , Debug ) ]
107
107
enum PatBoundCtx {
108
108
/// A product pattern context, e.g., `Variant(a, b)`.
109
109
Product ,
@@ -193,6 +193,27 @@ pub(crate) enum RibKind<'ra> {
193
193
/// No restriction needs to be applied.
194
194
Normal ,
195
195
196
+ /// During resolving an item in a block, we had records all bindings defined
197
+ /// in this local scope, for these features:
198
+ ///
199
+ /// - Forward reference detection:
200
+ ///
201
+ /// ```ignore (illustrative)
202
+ /// let a = b; // displays '`b` is defined at <span>' instead of ''b' not found'
203
+ /// let b = 42;
204
+ /// ```
205
+ ///
206
+ /// - Correctly resolves the hoisting bindings within macro expand:
207
+ ///
208
+ /// ```ignore (illustrative)
209
+ /// fn f() {}
210
+ /// let a: i16 = m!(); // throw error because it should use the local `f` rather than `fn f`
211
+ /// let f = || -> i16 { 42 };
212
+ /// macro_rules! m {() => ( f() )}
213
+ /// use m;
214
+ /// ```
215
+ Block { id : NodeId , is_module : bool } ,
216
+
196
217
/// We passed through an impl or trait and are now in one of its
197
218
/// methods or associated types. Allow references to ty params that impl or trait
198
219
/// binds. Disallow any other upvars (including other ty params that are
@@ -243,6 +264,7 @@ impl RibKind<'_> {
243
264
pub ( crate ) fn contains_params ( & self ) -> bool {
244
265
match self {
245
266
RibKind :: Normal
267
+ | RibKind :: Block { .. }
246
268
| RibKind :: FnOrCoroutine
247
269
| RibKind :: ConstantItem ( ..)
248
270
| RibKind :: Module ( _)
@@ -258,7 +280,7 @@ impl RibKind<'_> {
258
280
/// This rib forbids referring to labels defined in upwards ribs.
259
281
fn is_label_barrier ( self ) -> bool {
260
282
match self {
261
- RibKind :: Normal | RibKind :: MacroDefinition ( ..) => false ,
283
+ RibKind :: Normal | RibKind :: Block { .. } | RibKind :: MacroDefinition ( ..) => false ,
262
284
263
285
RibKind :: AssocItem
264
286
| RibKind :: FnOrCoroutine
@@ -740,7 +762,7 @@ struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
740
762
ribs : PerNS < Vec < Rib < ' ra > > > ,
741
763
742
764
/// Previous popped `rib`, only used for diagnostic.
743
- last_block_rib : Option < Rib < ' ra > > ,
765
+ last_normal_block_rib : Option < Rib < ' ra > > ,
744
766
745
767
/// The current set of local scopes, for labels.
746
768
label_ribs : Vec < Rib < ' ra , NodeId > > ,
@@ -1086,7 +1108,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
1086
1108
// Be sure not to set this until the function signature has been resolved.
1087
1109
let previous_state = replace ( & mut this. in_func_body , true ) ;
1088
1110
// We only care block in the same function
1089
- this. last_block_rib = None ;
1111
+ this. last_normal_block_rib = None ;
1090
1112
// Resolve the function body, potentially inside the body of an async closure
1091
1113
this. with_lifetime_rib (
1092
1114
LifetimeRibKind :: Elided ( LifetimeRes :: Infer ) ,
@@ -1434,7 +1456,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
1434
1456
type_ns : vec ! [ Rib :: new( start_rib_kind) ] ,
1435
1457
macro_ns : vec ! [ Rib :: new( start_rib_kind) ] ,
1436
1458
} ,
1437
- last_block_rib : None ,
1459
+ last_normal_block_rib : None ,
1438
1460
label_ribs : Vec :: new ( ) ,
1439
1461
lifetime_ribs : Vec :: new ( ) ,
1440
1462
lifetime_elision_candidates : None ,
@@ -2822,7 +2844,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
2822
2844
for parent_rib in self . ribs [ ns] . iter ( ) . rev ( ) {
2823
2845
// Break at mod level, to account for nested items which are
2824
2846
// allowed to shadow generic param names.
2825
- if matches ! ( parent_rib. kind, RibKind :: Module ( ..) ) {
2847
+ if matches ! (
2848
+ parent_rib. kind,
2849
+ RibKind :: Module ( ..) | RibKind :: Block { is_module: true , .. }
2850
+ ) {
2826
2851
break ;
2827
2852
}
2828
2853
@@ -3775,6 +3800,52 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
3775
3800
fn resolve_pattern_top ( & mut self , pat : & ' ast Pat , pat_src : PatternSource ) {
3776
3801
let mut bindings = smallvec ! [ ( PatBoundCtx :: Product , Default :: default ( ) ) ] ;
3777
3802
self . resolve_pattern ( pat, pat_src, & mut bindings) ;
3803
+
3804
+ let mut last_pat_id = None ;
3805
+ pat. walk ( & mut |pat| {
3806
+ if let PatKind :: Ident ( ..) = pat. kind {
3807
+ last_pat_id = Some ( pat. id ) ;
3808
+ }
3809
+ true
3810
+ } ) ;
3811
+
3812
+ if let Some ( last_pat_id) = last_pat_id
3813
+ && let RibKind :: Block { id : block, .. } = self . ribs [ ValueNS ] . last_mut ( ) . unwrap ( ) . kind
3814
+ && let Some ( items) = self . r . lookahead_items_in_block . get_mut ( & block)
3815
+ {
3816
+ let start = items. get_index_of ( & last_pat_id) . unwrap_or_else ( || {
3817
+ panic ! ( "pattern({pat:#?}) not found in lookahead items" ) ;
3818
+ } ) ;
3819
+ // let mut first_macro: Option<SyntaxContext> = None;
3820
+ // `need_removed` used for avoid injecting masked names into macro definition bindings:
3821
+ //
3822
+ // ```
3823
+ // let x = 0;
3824
+ // macro_rules! m0 {() => { x; }} // Injects `let x = 0` into `m0`
3825
+ // let x = 1;
3826
+ // macro_rules! m1 {() => { x; }} // Should NOT inject `let x = 0` into `m1`
3827
+ // ```
3828
+ let mut need_removed = FxHashSet :: default ( ) ;
3829
+ for ( _, item) in items. iter_mut ( ) . skip ( start + 1 ) {
3830
+ match item {
3831
+ LookaheadItemInBlock :: Binding { name } => {
3832
+ need_removed. insert ( name. normalize_to_macro_rules ( ) ) ;
3833
+ }
3834
+ LookaheadItemInBlock :: MacroDef { bindings : macro_bindings, .. } => {
3835
+ let bindings =
3836
+ bindings. last ( ) . unwrap ( ) . 1 . iter ( ) . filter_map ( |( name, res) | {
3837
+ if !need_removed. contains ( & name) {
3838
+ Some ( ( * name, * res) )
3839
+ } else {
3840
+ None
3841
+ }
3842
+ } ) ;
3843
+ macro_bindings. extend ( bindings) ;
3844
+ }
3845
+ }
3846
+ }
3847
+ }
3848
+
3778
3849
self . apply_pattern_bindings ( bindings) ;
3779
3850
}
3780
3851
@@ -4658,6 +4729,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4658
4729
// Move down in the graph, if there's an anonymous module rooted here.
4659
4730
let orig_module = self . parent_scope . module ;
4660
4731
let anonymous_module = self . r . block_map . get ( & block. id ) . cloned ( ) ; // clones a reference
4732
+ let is_module_block = anonymous_module. is_some ( ) ;
4661
4733
4662
4734
let mut num_macro_definition_ribs = 0 ;
4663
4735
if let Some ( anonymous_module) = anonymous_module {
@@ -4669,14 +4741,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4669
4741
self . ribs [ ValueNS ] . push ( Rib :: new ( RibKind :: Normal ) ) ;
4670
4742
}
4671
4743
4744
+ self . ribs [ ValueNS ]
4745
+ . push ( Rib :: new ( RibKind :: Block { id : block. id , is_module : is_module_block } ) ) ;
4672
4746
// Descend into the block.
4673
4747
for stmt in & block. stmts {
4674
4748
if let StmtKind :: Item ( ref item) = stmt. kind
4675
4749
&& let ItemKind :: MacroDef ( ..) = item. kind
4676
4750
{
4677
4751
num_macro_definition_ribs += 1 ;
4678
4752
let res = self . r . local_def_id ( item. id ) . to_def_id ( ) ;
4679
- self . ribs [ ValueNS ] . push ( Rib :: new ( RibKind :: MacroDefinition ( res) ) ) ;
4680
4753
self . label_ribs . push ( Rib :: new ( RibKind :: MacroDefinition ( res) ) ) ;
4681
4754
}
4682
4755
@@ -4686,10 +4759,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
4686
4759
// Move back up.
4687
4760
self . parent_scope . module = orig_module;
4688
4761
for _ in 0 ..num_macro_definition_ribs {
4689
- self . ribs [ ValueNS ] . pop ( ) ;
4762
+ // pop `MacroDefinition`
4690
4763
self . label_ribs . pop ( ) ;
4691
4764
}
4692
- self . last_block_rib = self . ribs [ ValueNS ] . pop ( ) ;
4765
+ let block_rib = self . ribs [ ValueNS ] . pop ( ) ; // pop `RibKind::Block`
4766
+ if !is_module_block {
4767
+ self . last_normal_block_rib = block_rib;
4768
+ }
4769
+ self . ribs [ ValueNS ] . pop ( ) ; // pop `RibKind::Module` or `RibKind::Normal`
4693
4770
if anonymous_module. is_some ( ) {
4694
4771
self . ribs [ TypeNS ] . pop ( ) ;
4695
4772
}
@@ -5146,6 +5223,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
5146
5223
/// lifetime generic parameters and function parameters.
5147
5224
struct ItemInfoCollector < ' a , ' ra , ' tcx > {
5148
5225
r : & ' a mut Resolver < ' ra , ' tcx > ,
5226
+ current_block : Option < NodeId > ,
5149
5227
}
5150
5228
5151
5229
impl ItemInfoCollector < ' _ , ' _ , ' _ > {
@@ -5165,6 +5243,30 @@ impl ItemInfoCollector<'_, '_, '_> {
5165
5243
} ;
5166
5244
self . r . delegation_fn_sigs . insert ( self . r . local_def_id ( id) , sig) ;
5167
5245
}
5246
+
5247
+ fn collect_fresh_binding ( & mut self , binding : NodeId , name : Ident ) {
5248
+ let block_id = self . current_block . unwrap ( ) ;
5249
+ let items = self . r . lookahead_items_in_block . entry ( block_id) . or_default ( ) ;
5250
+ items. insert ( binding, LookaheadItemInBlock :: Binding { name } ) ;
5251
+ }
5252
+
5253
+ fn collect_macro_def_in_block ( & mut self , block_id : NodeId , node_id : NodeId ) {
5254
+ let def_id = self . r . local_def_id ( node_id) . to_def_id ( ) ;
5255
+ let items = self . r . lookahead_items_in_block . entry ( block_id) . or_default ( ) ;
5256
+ items. insert (
5257
+ node_id,
5258
+ LookaheadItemInBlock :: MacroDef { bindings : Default :: default ( ) , def_id } ,
5259
+ ) ;
5260
+ }
5261
+
5262
+ fn collect_fresh_binding_in_pat ( & mut self , pat : & ast:: Pat ) {
5263
+ pat. walk ( & mut |pat| {
5264
+ if let PatKind :: Ident ( _, name, _) = & pat. kind {
5265
+ self . collect_fresh_binding ( pat. id , * name) ;
5266
+ }
5267
+ true
5268
+ } ) ;
5269
+ }
5168
5270
}
5169
5271
5170
5272
impl < ' ast > Visitor < ' ast > for ItemInfoCollector < ' _ , ' _ , ' _ > {
@@ -5201,12 +5303,15 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
5201
5303
}
5202
5304
}
5203
5305
}
5204
-
5306
+ ItemKind :: MacroDef ( _, _) => {
5307
+ if let Some ( block_id) = self . current_block {
5308
+ self . collect_macro_def_in_block ( block_id, item. id ) ;
5309
+ }
5310
+ }
5205
5311
ItemKind :: Mod ( ..)
5206
5312
| ItemKind :: Static ( ..)
5207
5313
| ItemKind :: Use ( ..)
5208
5314
| ItemKind :: ExternCrate ( ..)
5209
- | ItemKind :: MacroDef ( ..)
5210
5315
| ItemKind :: GlobalAsm ( ..)
5211
5316
| ItemKind :: MacCall ( ..)
5212
5317
| ItemKind :: DelegationMac ( ..) => { }
@@ -5226,11 +5331,22 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
5226
5331
}
5227
5332
visit:: walk_assoc_item ( self , item, ctxt) ;
5228
5333
}
5334
+
5335
+ fn visit_local ( & mut self , node : & ' ast Local ) -> Self :: Result {
5336
+ self . collect_fresh_binding_in_pat ( & node. pat ) ;
5337
+ visit:: walk_local ( self , node)
5338
+ }
5339
+
5340
+ fn visit_block ( & mut self , node : & ' ast Block ) -> Self :: Result {
5341
+ let saved_block_id = self . current_block . replace ( node. id ) ;
5342
+ visit:: walk_block ( self , node) ;
5343
+ self . current_block = saved_block_id;
5344
+ }
5229
5345
}
5230
5346
5231
5347
impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
5232
5348
pub ( crate ) fn late_resolve_crate ( & mut self , krate : & Crate ) {
5233
- visit:: walk_crate ( & mut ItemInfoCollector { r : self } , krate) ;
5349
+ visit:: walk_crate ( & mut ItemInfoCollector { r : self , current_block : None } , krate) ;
5234
5350
let mut late_resolution_visitor = LateResolutionVisitor :: new ( self ) ;
5235
5351
late_resolution_visitor. resolve_doc_links ( & krate. attrs , MaybeExported :: Ok ( CRATE_NODE_ID ) ) ;
5236
5352
visit:: walk_crate ( & mut late_resolution_visitor, krate) ;
0 commit comments