@@ -40,6 +40,13 @@ enum Shadowing {
40
40
Unrestricted ,
41
41
}
42
42
43
+ pub ( crate ) enum ResolveIdentInBlockRes < ' ra > {
44
+ Res ( Res ) ,
45
+ Item ( NameBinding < ' ra > ) ,
46
+ DefinedLater { def_site : Span } ,
47
+ NotFound ,
48
+ }
49
+
43
50
impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
44
51
/// A generic scope visitor.
45
52
/// Visits scopes in order to resolve some identifier in them or perform other actions.
@@ -270,6 +277,158 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
270
277
None
271
278
}
272
279
280
+ pub ( crate ) fn resolve_ident_in_block_lexical_scope (
281
+ & mut self ,
282
+ ident : & mut Ident ,
283
+ ns : Namespace ,
284
+ parent_scope : & ParentScope < ' ra > ,
285
+ finalize : Option < Finalize > ,
286
+ rib_index : usize ,
287
+ ribs : & [ Rib < ' ra > ] ,
288
+ ignore_binding : Option < NameBinding < ' ra > > ,
289
+ ) -> ResolveIdentInBlockRes < ' ra > {
290
+ fn resolve_ident_in_forward_macro_of_block < ' ra > (
291
+ r : & mut Resolver < ' ra , ' _ > ,
292
+ expansion : & mut Option < NodeId > , // macro_def_id
293
+ module : Module < ' ra > ,
294
+ resolving_block : NodeId ,
295
+ ident : & mut Ident ,
296
+ rib_index : usize ,
297
+ finalize : Option < Finalize > ,
298
+ ribs : & [ Rib < ' ra > ] ,
299
+ ) -> Option < Res > {
300
+ let items = r. lookahead_items_in_block . get ( & resolving_block) ?;
301
+ for ( node_id, item) in items. iter ( ) . rev ( ) {
302
+ match item {
303
+ LookaheadItemInBlock :: MacroDef { def_id } => {
304
+ if * def_id != r. macro_def ( ident. span . ctxt ( ) ) {
305
+ continue ;
306
+ }
307
+ expansion. get_or_insert ( * node_id) ;
308
+ ident. span . remove_mark ( ) ;
309
+ if let Some ( ( original_rib_ident_def, ( module_of_res, res, _) ) ) =
310
+ r. bindings_of_macro_def [ def_id] . get_key_value ( ident)
311
+ && module_of_res. is_ancestor_of ( module)
312
+ {
313
+ // The ident resolves to a type parameter or local variable.
314
+ return Some ( r. validate_res_from_ribs (
315
+ rib_index,
316
+ * ident,
317
+ * res,
318
+ finalize. map ( |finalize| finalize. path_span ) ,
319
+ * original_rib_ident_def,
320
+ ribs,
321
+ ) ) ;
322
+ }
323
+ }
324
+ LookaheadItemInBlock :: Block => {
325
+ // resolve child block later
326
+ }
327
+ LookaheadItemInBlock :: Binding { .. } => { }
328
+ }
329
+ }
330
+
331
+ let subs = items
332
+ . iter ( )
333
+ . filter_map ( |( node_id, item) | {
334
+ if matches ! ( item, LookaheadItemInBlock :: Block ) { Some ( * node_id) } else { None }
335
+ } )
336
+ . collect :: < Vec < _ > > ( ) ;
337
+ for node_id in subs {
338
+ if let Some ( res) = resolve_ident_in_forward_macro_of_block (
339
+ r, expansion, module, node_id, ident, rib_index, finalize, ribs,
340
+ ) {
341
+ return Some ( res) ;
342
+ }
343
+ }
344
+
345
+ None
346
+ }
347
+
348
+ fn is_defined_later (
349
+ r : & Resolver < ' _ , ' _ > ,
350
+ macro_def_node : NodeId ,
351
+ resolving_block : NodeId ,
352
+ ident : & Ident ,
353
+ ) -> Option < Span > {
354
+ let Some ( items) = r. lookahead_items_in_block . get ( & resolving_block) else {
355
+ return None ;
356
+ } ;
357
+ for ( node_id, item) in items {
358
+ match item {
359
+ LookaheadItemInBlock :: Binding { name } => {
360
+ if name. name == ident. name {
361
+ return Some ( name. span ) ;
362
+ }
363
+ }
364
+ LookaheadItemInBlock :: Block => {
365
+ if let Some ( def_span) = is_defined_later ( r, macro_def_node, * node_id, ident)
366
+ {
367
+ return Some ( def_span) ;
368
+ }
369
+ }
370
+ LookaheadItemInBlock :: MacroDef { .. } => {
371
+ if macro_def_node. eq ( node_id) {
372
+ return None ;
373
+ }
374
+ }
375
+ }
376
+ }
377
+
378
+ None
379
+ }
380
+
381
+ let RibKind :: Block { module : block_module, id : resolving_block } = ribs[ rib_index] . kind
382
+ else {
383
+ bug ! ( "expected a block rib" ) ;
384
+ } ;
385
+ let mut expansion = None ;
386
+ if let Some ( res) = resolve_ident_in_forward_macro_of_block (
387
+ self ,
388
+ & mut expansion,
389
+ parent_scope. module ,
390
+ resolving_block,
391
+ ident,
392
+ rib_index,
393
+ finalize,
394
+ ribs,
395
+ ) {
396
+ return ResolveIdentInBlockRes :: Res ( res) ;
397
+ }
398
+
399
+ if let Some ( expansion) = expansion
400
+ && let Some ( def_site) = is_defined_later ( self , expansion, resolving_block, & ident)
401
+ {
402
+ // return `None` for this case:
403
+ //
404
+ // ```
405
+ // let a = m!();
406
+ // let b = 1;
407
+ // macro_rules! m { () => { b } }
408
+ // use b;
409
+ // ```
410
+ return ResolveIdentInBlockRes :: DefinedLater { def_site } ;
411
+ }
412
+
413
+ if let Some ( module) = block_module
414
+ && let Ok ( binding) = self . cm ( ) . resolve_ident_in_module_unadjusted (
415
+ ModuleOrUniformRoot :: Module ( module) ,
416
+ * ident,
417
+ ns,
418
+ parent_scope,
419
+ Shadowing :: Unrestricted ,
420
+ finalize. map ( |finalize| Finalize { used : Used :: Scope , ..finalize } ) ,
421
+ ignore_binding,
422
+ None ,
423
+ )
424
+ {
425
+ // The ident resolves to an item in a block.
426
+ return ResolveIdentInBlockRes :: Item ( binding) ;
427
+ }
428
+
429
+ ResolveIdentInBlockRes :: NotFound
430
+ }
431
+
273
432
/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
274
433
/// More specifically, we proceed up the hierarchy of scopes and return the binding for
275
434
/// `ident` in the first scope that defines it (or None if no scopes define it).
@@ -328,143 +487,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
328
487
* original_rib_ident_def,
329
488
ribs,
330
489
) ) ) ;
331
- } else if let RibKind :: Block { module, id : block_id } = rib. kind {
332
- fn resolve_ident_in_forward_macro_of_block < ' ra > (
333
- r : & mut Resolver < ' ra , ' _ > ,
334
- expansion : & mut Option < NodeId > , // macro_def_id
335
- module : Module < ' ra > ,
336
- resolving_block : NodeId ,
337
- ident : & mut Ident ,
338
- i : usize ,
339
- finalize : Option < Finalize > ,
340
- ribs : & [ Rib < ' ra > ] ,
341
- ) -> Option < Res > {
342
- let items = r. lookahead_items_in_block . get ( & resolving_block) ?;
343
- for ( node_id, item) in items. iter ( ) . rev ( ) {
344
- match item {
345
- LookaheadItemInBlock :: MacroDef { def_id } => {
346
- if * def_id != r. macro_def ( ident. span . ctxt ( ) ) {
347
- continue ;
348
- }
349
- expansion. get_or_insert ( * node_id) ;
350
- ident. span . remove_mark ( ) ;
351
- if let Some ( ( original_rib_ident_def, ( module_of_res, res, _) ) ) =
352
- r. bindings_of_macro_def [ def_id] . get_key_value ( ident)
353
- && module_of_res. is_ancestor_of ( module)
354
- {
355
- // The ident resolves to a type parameter or local variable.
356
- return Some ( r. validate_res_from_ribs (
357
- i,
358
- * ident,
359
- * res,
360
- finalize. map ( |finalize| finalize. path_span ) ,
361
- * original_rib_ident_def,
362
- ribs,
363
- ) ) ;
364
- }
365
- }
366
- LookaheadItemInBlock :: Block => {
367
- // resolve child block later
368
- }
369
- LookaheadItemInBlock :: Binding { .. } => { }
370
- }
371
- }
372
-
373
- let subs = items
374
- . iter ( )
375
- . filter_map ( |( node_id, item) | {
376
- if matches ! ( item, LookaheadItemInBlock :: Block ) {
377
- Some ( * node_id)
378
- } else {
379
- None
380
- }
381
- } )
382
- . collect :: < Vec < _ > > ( ) ;
383
- for node_id in subs {
384
- if let Some ( res) = resolve_ident_in_forward_macro_of_block (
385
- r, expansion, module, node_id, ident, i, finalize, ribs,
386
- ) {
387
- return Some ( res) ;
388
- }
389
- }
390
-
391
- None
392
- }
393
-
394
- fn is_defined_later (
395
- r : & Resolver < ' _ , ' _ > ,
396
- expansion : NodeId , // macro_def_id
397
- block_id : NodeId ,
398
- ident : & Ident ,
399
- ) -> bool {
400
- let Some ( items) = r. lookahead_items_in_block . get ( & block_id) else {
401
- return false ;
402
- } ;
403
- for ( node_id, item) in items {
404
- match item {
405
- LookaheadItemInBlock :: Binding { name } => {
406
- if name. name == ident. name {
407
- return true ;
408
- }
409
- }
410
- LookaheadItemInBlock :: Block => {
411
- if is_defined_later ( r, expansion, * node_id, ident) {
412
- return true ;
413
- }
414
- }
415
- LookaheadItemInBlock :: MacroDef { .. } => {
416
- if expansion. eq ( node_id) {
417
- return false ;
418
- }
419
- }
420
- }
421
- }
422
-
423
- false
424
- }
425
-
426
- let mut expansion = None ;
427
- if let Some ( res) = resolve_ident_in_forward_macro_of_block (
428
- self ,
429
- & mut expansion,
430
- parent_scope. module ,
431
- block_id,
490
+ } else if let RibKind :: Block { .. } = rib. kind {
491
+ match self . resolve_ident_in_block_lexical_scope (
432
492
& mut ident,
433
- i,
493
+ ns,
494
+ parent_scope,
434
495
finalize,
496
+ i,
435
497
ribs,
498
+ ignore_binding,
436
499
) {
437
- return Some ( LexicalScopeBinding :: Res ( res) ) ;
438
- }
439
-
440
- if let Some ( expansion) = expansion
441
- && is_defined_later ( self , expansion, block_id, & ident)
442
- {
443
- // return `None` for this case:
444
- //
445
- // ```
446
- // let a = m!();
447
- // let b = 1;
448
- // macro_rules! m { () => { b } }
449
- // use b;
450
- // ```
451
- return None ;
452
- }
453
-
454
- if let Some ( module) = module
455
- && let Ok ( binding) = self . cm ( ) . resolve_ident_in_module_unadjusted (
456
- ModuleOrUniformRoot :: Module ( module) ,
457
- ident,
458
- ns,
459
- parent_scope,
460
- Shadowing :: Unrestricted ,
461
- finalize. map ( |finalize| Finalize { used : Used :: Scope , ..finalize } ) ,
462
- ignore_binding,
463
- None ,
464
- )
465
- {
466
- // The ident resolves to an item in a block.
467
- return Some ( LexicalScopeBinding :: Item ( binding) ) ;
500
+ ResolveIdentInBlockRes :: Res ( res) => return Some ( LexicalScopeBinding :: Res ( res) ) ,
501
+ ResolveIdentInBlockRes :: Item ( item) => {
502
+ return Some ( LexicalScopeBinding :: Item ( item) ) ;
503
+ }
504
+ ResolveIdentInBlockRes :: DefinedLater { .. } => return None ,
505
+ ResolveIdentInBlockRes :: NotFound => { }
468
506
}
469
507
} else if let RibKind :: Module ( module) = rib. kind {
470
508
// Encountered a module item, abandon ribs and look into that module and preludes.
0 commit comments