@@ -39,9 +39,9 @@ use thin_vec::ThinVec;
3939use tracing:: { debug, instrument, trace} ;
4040
4141use crate :: {
42- BindingError , BindingKey , Finalize , LexicalScopeBinding , Module , ModuleOrUniformRoot ,
43- NameBinding , ParentScope , PathResult , ResolutionError , Resolver , Segment , TyCtxt , UseError ,
44- Used , errors, path_names_to_string, rustdoc,
42+ BindingError , BindingKey , Finalize , LexicalScopeBinding , LookaheadItemInBlock , Module ,
43+ ModuleOrUniformRoot , NameBinding , ParentScope , PathResult , ResolutionError , Resolver , Segment ,
44+ TyCtxt , UseError , Used , errors, path_names_to_string, rustdoc,
4545} ;
4646
4747mod diagnostics;
@@ -102,7 +102,7 @@ impl IntoDiagArg for PatternSource {
102102/// Denotes whether the context for the set of already bound bindings is a `Product`
103103/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
104104/// See those functions for more information.
105- #[ derive( PartialEq ) ]
105+ #[ derive( PartialEq , Debug ) ]
106106enum PatBoundCtx {
107107 /// A product pattern context, e.g., `Variant(a, b)`.
108108 Product ,
@@ -197,7 +197,29 @@ pub(crate) enum RibKind<'ra> {
197197 /// `Block(None)` must be always processed in the same way as `Block(Some(module))`
198198 /// with empty `module`. The module can be `None` only because creation of some definitely
199199 /// empty modules is skipped as an optimization.
200- Block ( Option < Module < ' ra > > ) ,
200+ Block {
201+ module : Option < Module < ' ra > > ,
202+ /// The node id of block kind, which stores all bindings defined in
203+ /// this local scope, for these features:
204+ ///
205+ /// - Forward reference detection:
206+ ///
207+ /// ```ignore (illustrative)
208+ /// let a = b; // displays '`b` is defined at <span>' instead of ''b' not found'
209+ /// let b = 42;
210+ /// ```
211+ ///
212+ /// - Correctly resolves the hoisting bindings within macro expand:
213+ ///
214+ /// ```ignore (illustrative)
215+ /// fn f() {}
216+ /// let a: i16 = m!(); // throw error because it should use the local `f` rather than `fn f`
217+ /// let f = || -> i16 { 42 };
218+ /// macro_rules! m {() => ( f() )}
219+ /// use m;
220+ /// ```
221+ id : NodeId ,
222+ } ,
201223
202224 /// We passed through an impl or trait and are now in one of its
203225 /// methods or associated types. Allow references to ty params that impl or trait
@@ -249,7 +271,7 @@ impl RibKind<'_> {
249271 pub ( crate ) fn contains_params ( & self ) -> bool {
250272 match self {
251273 RibKind :: Normal
252- | RibKind :: Block ( .. )
274+ | RibKind :: Block { .. }
253275 | RibKind :: FnOrCoroutine
254276 | RibKind :: ConstantItem ( ..)
255277 | RibKind :: Module ( _)
@@ -2816,7 +2838,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
28162838 for parent_rib in self . ribs [ ns] . iter ( ) . rev ( ) {
28172839 // Break at module or block level, to account for nested items which are
28182840 // allowed to shadow generic param names.
2819- if matches ! ( parent_rib. kind, RibKind :: Module ( ..) | RibKind :: Block ( .. ) ) {
2841+ if matches ! ( parent_rib. kind, RibKind :: Module ( ..) | RibKind :: Block { .. } ) {
28202842 break ;
28212843 }
28222844
@@ -3769,6 +3791,52 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37693791 fn resolve_pattern_top ( & mut self , pat : & ' ast Pat , pat_src : PatternSource ) {
37703792 let mut bindings = smallvec ! [ ( PatBoundCtx :: Product , Default :: default ( ) ) ] ;
37713793 self . resolve_pattern ( pat, pat_src, & mut bindings) ;
3794+
3795+ let mut last_pat_id = None ;
3796+ pat. walk ( & mut |pat| {
3797+ if let PatKind :: Ident ( ..) = pat. kind {
3798+ last_pat_id = Some ( pat. id ) ;
3799+ }
3800+ true
3801+ } ) ;
3802+
3803+ if let Some ( last_pat_id) = last_pat_id
3804+ && let RibKind :: Block { id : block, .. } = self . ribs [ ValueNS ] . last_mut ( ) . unwrap ( ) . kind
3805+ && let Some ( items) = self . r . lookahead_items_in_block . get_mut ( & block)
3806+ {
3807+ let start = items. get_index_of ( & last_pat_id) . unwrap_or_else ( || {
3808+ panic ! ( "pattern({pat:#?}) not found in lookahead items" ) ;
3809+ } ) ;
3810+ // let mut first_macro: Option<SyntaxContext> = None;
3811+ // `need_removed` used for avoid injecting masked names into macro definition bindings:
3812+ //
3813+ // ```
3814+ // let x = 0;
3815+ // macro_rules! m0 {() => { x; }} // Injects `let x = 0` into `m0`
3816+ // let x = 1;
3817+ // macro_rules! m1 {() => { x; }} // Should NOT inject `let x = 0` into `m1`
3818+ // ```
3819+ let mut need_removed = FxHashSet :: default ( ) ;
3820+ for ( _, item) in items. iter_mut ( ) . skip ( start + 1 ) {
3821+ match item {
3822+ LookaheadItemInBlock :: Binding { name } => {
3823+ need_removed. insert ( name. normalize_to_macro_rules ( ) ) ;
3824+ }
3825+ LookaheadItemInBlock :: MacroDef { bindings : macro_bindings, .. } => {
3826+ let bindings =
3827+ bindings. last ( ) . unwrap ( ) . 1 . iter ( ) . filter_map ( |( name, res) | {
3828+ if !need_removed. contains ( & name) {
3829+ Some ( ( * name, * res) )
3830+ } else {
3831+ None
3832+ }
3833+ } ) ;
3834+ macro_bindings. extend ( bindings) ;
3835+ }
3836+ }
3837+ }
3838+ }
3839+
37723840 self . apply_pattern_bindings ( bindings) ;
37733841 }
37743842
@@ -4650,11 +4718,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46504718 let mut num_macro_definition_ribs = 0 ;
46514719 if let Some ( anonymous_module) = anonymous_module {
46524720 debug ! ( "(resolving block) found anonymous module, moving down" ) ;
4653- self . ribs [ ValueNS ] . push ( Rib :: new ( RibKind :: Block ( Some ( anonymous_module) ) ) ) ;
4654- self . ribs [ TypeNS ] . push ( Rib :: new ( RibKind :: Block ( Some ( anonymous_module) ) ) ) ;
4721+ let rib_kind = RibKind :: Block { module : Some ( anonymous_module) , id : block. id } ;
4722+ self . ribs [ ValueNS ] . push ( Rib :: new ( rib_kind) ) ;
4723+ self . ribs [ TypeNS ] . push ( Rib :: new ( rib_kind) ) ;
46554724 self . parent_scope . module = anonymous_module;
46564725 } else {
4657- self . ribs [ ValueNS ] . push ( Rib :: new ( RibKind :: Block ( None ) ) ) ;
4726+ self . ribs [ ValueNS ] . push ( Rib :: new ( RibKind :: Block { module : None , id : block . id } ) ) ;
46584727 }
46594728
46604729 // Descend into the block.
@@ -4664,7 +4733,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46644733 {
46654734 num_macro_definition_ribs += 1 ;
46664735 let res = self . r . local_def_id ( item. id ) . to_def_id ( ) ;
4667- self . ribs [ ValueNS ] . push ( Rib :: new ( RibKind :: MacroDefinition ( res) ) ) ;
46684736 self . label_ribs . push ( Rib :: new ( RibKind :: MacroDefinition ( res) ) ) ;
46694737 }
46704738
@@ -4674,7 +4742,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46744742 // Move back up.
46754743 self . parent_scope . module = orig_module;
46764744 for _ in 0 ..num_macro_definition_ribs {
4677- self . ribs [ ValueNS ] . pop ( ) ;
4745+ // pop `MacroDefinition`
46784746 self . label_ribs . pop ( ) ;
46794747 }
46804748 self . last_block_rib = self . ribs [ ValueNS ] . pop ( ) ;
@@ -5134,6 +5202,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
51345202/// lifetime generic parameters and function parameters.
51355203struct ItemInfoCollector < ' a , ' ra , ' tcx > {
51365204 r : & ' a mut Resolver < ' ra , ' tcx > ,
5205+ current_block : Option < NodeId > ,
51375206}
51385207
51395208impl ItemInfoCollector < ' _ , ' _ , ' _ > {
@@ -5189,12 +5258,20 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
51895258 }
51905259 }
51915260 }
5192-
5261+ ItemKind :: MacroDef ( _, _) => {
5262+ if let Some ( block_id) = self . current_block {
5263+ let def_id = self . r . local_def_id ( item. id ) . to_def_id ( ) ;
5264+ let items = self . r . lookahead_items_in_block . entry ( block_id) . or_default ( ) ;
5265+ items. insert (
5266+ item. id ,
5267+ LookaheadItemInBlock :: MacroDef { bindings : Default :: default ( ) , def_id } ,
5268+ ) ;
5269+ }
5270+ }
51935271 ItemKind :: Mod ( ..)
51945272 | ItemKind :: Static ( ..)
51955273 | ItemKind :: Use ( ..)
51965274 | ItemKind :: ExternCrate ( ..)
5197- | ItemKind :: MacroDef ( ..)
51985275 | ItemKind :: GlobalAsm ( ..)
51995276 | ItemKind :: MacCall ( ..)
52005277 | ItemKind :: DelegationMac ( ..) => { }
@@ -5214,11 +5291,30 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
52145291 }
52155292 visit:: walk_assoc_item ( self , item, ctxt) ;
52165293 }
5294+
5295+ fn visit_local ( & mut self , node : & ' ast Local ) -> Self :: Result {
5296+ // collect local bindings into block
5297+ node. pat . walk ( & mut |pat| {
5298+ if let PatKind :: Ident ( _, name, _) = & pat. kind {
5299+ let block_id = self . current_block . unwrap ( ) ;
5300+ let items = self . r . lookahead_items_in_block . entry ( block_id) . or_default ( ) ;
5301+ items. insert ( pat. id , LookaheadItemInBlock :: Binding { name : * name } ) ;
5302+ }
5303+ true
5304+ } ) ;
5305+ visit:: walk_local ( self , node)
5306+ }
5307+
5308+ fn visit_block ( & mut self , node : & ' ast Block ) -> Self :: Result {
5309+ let saved_block_id = self . current_block . replace ( node. id ) ;
5310+ visit:: walk_block ( self , node) ;
5311+ self . current_block = saved_block_id;
5312+ }
52175313}
52185314
52195315impl < ' ra , ' tcx > Resolver < ' ra , ' tcx > {
52205316 pub ( crate ) fn late_resolve_crate ( & mut self , krate : & Crate ) {
5221- visit:: walk_crate ( & mut ItemInfoCollector { r : self } , krate) ;
5317+ visit:: walk_crate ( & mut ItemInfoCollector { r : self , current_block : None } , krate) ;
52225318 let mut late_resolution_visitor = LateResolutionVisitor :: new ( self ) ;
52235319 late_resolution_visitor. resolve_doc_links ( & krate. attrs , MaybeExported :: Ok ( CRATE_NODE_ID ) ) ;
52245320 visit:: walk_crate ( & mut late_resolution_visitor, krate) ;
0 commit comments