@@ -40,6 +40,13 @@ enum Shadowing {
4040 Unrestricted ,
4141}
4242
43+ pub ( crate ) enum ResolveIdentInBlockRes < ' ra > {
44+ Res ( Res ) ,
45+ Item ( NameBinding < ' ra > ) ,
46+ DefinedLater { def_site : Span } ,
47+ NotFound ,
48+ }
49+
4350impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
4451 /// A generic scope visitor.
4552 /// Visits scopes in order to resolve some identifier in them or perform other actions.
@@ -270,6 +277,158 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
270277 None
271278 }
272279
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+
273432 /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
274433 /// More specifically, we proceed up the hierarchy of scopes and return the binding for
275434 /// `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> {
328487 * original_rib_ident_def,
329488 ribs,
330489 ) ) ) ;
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 (
432492 & mut ident,
433- i,
493+ ns,
494+ parent_scope,
434495 finalize,
496+ i,
435497 ribs,
498+ ignore_binding,
436499 ) {
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 => { }
468506 }
469507 } else if let RibKind :: Module ( module) = rib. kind {
470508 // Encountered a module item, abandon ribs and look into that module and preludes.
0 commit comments