@@ -103,7 +103,7 @@ impl IntoDiagArg for PatternSource {
103103/// Denotes whether the context for the set of already bound bindings is a `Product`
104104/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
105105/// See those functions for more information.
106- #[ derive( PartialEq ) ]
106+ #[ derive( PartialEq , Debug ) ]
107107enum PatBoundCtx {
108108 /// A product pattern context, e.g., `Variant(a, b)`.
109109 Product ,
@@ -217,6 +217,41 @@ pub(crate) enum RibKind<'ra> {
217217 /// We passed through a `macro_rules!` statement
218218 MacroDefinition ( DefId ) ,
219219
220+ /// Collects `macro_rules!` statements prior to resolution.
221+ /// For example:
222+ ///
223+ /// ```ignore (illustrative)
224+ /// let f = || -> i16 { 42 }; // <1>
225+ /// let a: i16 = m!(); // <2>
226+ /// macro_rules! m {() => ( f() )} // <3>
227+ /// use m; // <4>
228+ /// ```
229+ ///
230+ /// We record `<1>` when resolving the value of `<2>` (the expansion
231+ /// result of `<3>`), enabling the system to recognize that `<1>` is
232+ /// referenced in `<3>`.
233+ ///
234+ /// ### Why Not Use `MacroDefinition` Directly?
235+ ///
236+ /// This prevents edge cases like:
237+ ///
238+ /// ```ignore (illustrative)
239+ /// fn f() {
240+ /// let x = 0; // <1>
241+ /// macro_rules! foo {
242+ /// () => {
243+ /// assert_eq!(x, 0);
244+ /// }
245+ /// }
246+ /// let x = 1; // <2>
247+ /// foo!();
248+ /// }
249+ /// ```
250+ ///
251+ /// Using `MacroDefinition` would incorrectly record both `<1>` and `<2>` as
252+ /// potential resolutions for `x` within the macro, leading to assertion failed.
253+ LookAheadMacroDefinition ( DefId ) ,
254+
220255 /// All bindings in this rib are generic parameters that can't be used
221256 /// from the default of a generic parameter because they're not declared
222257 /// before said generic parameter. Also see the `visit_generics` override.
@@ -247,6 +282,7 @@ impl RibKind<'_> {
247282 | RibKind :: ConstantItem ( ..)
248283 | RibKind :: Module ( _)
249284 | RibKind :: MacroDefinition ( _)
285+ | RibKind :: LookAheadMacroDefinition ( _)
250286 | RibKind :: InlineAsmSym => false ,
251287 RibKind :: ConstParamTy
252288 | RibKind :: AssocItem
@@ -258,7 +294,9 @@ impl RibKind<'_> {
258294 /// This rib forbids referring to labels defined in upwards ribs.
259295 fn is_label_barrier ( self ) -> bool {
260296 match self {
261- RibKind :: Normal | RibKind :: MacroDefinition ( ..) => false ,
297+ RibKind :: Normal
298+ | RibKind :: MacroDefinition ( ..)
299+ | RibKind :: LookAheadMacroDefinition ( ..) => false ,
262300
263301 RibKind :: AssocItem
264302 | RibKind :: FnOrCoroutine
@@ -3793,17 +3831,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37933831
37943832 /// Apply the bindings from a pattern to the innermost rib of the current scope.
37953833 fn apply_pattern_bindings ( & mut self , mut pat_bindings : PatternBindings ) {
3796- let rib_bindings = self . innermost_rib_bindings ( ValueNS ) ;
37973834 let Some ( ( _, pat_bindings) ) = pat_bindings. pop ( ) else {
37983835 bug ! ( "tried applying nonexistent bindings from pattern" ) ;
37993836 } ;
3800-
3801- if rib_bindings. is_empty ( ) {
3802- // Often, such as for match arms, the bindings are introduced into a new rib.
3803- // In this case, we can move the bindings over directly.
3804- * rib_bindings = pat_bindings;
3805- } else {
3806- rib_bindings. extend ( pat_bindings) ;
3837+ for rib in self . ribs [ ValueNS ] . iter_mut ( ) . rev ( ) {
3838+ let stop = !matches ! ( rib. kind, RibKind :: LookAheadMacroDefinition ( _) ) ;
3839+ if rib. bindings . is_empty ( ) {
3840+ // Often, such as for match arms, the bindings are introduced into a new rib.
3841+ // In this case, we can move the bindings over directly.
3842+ rib. bindings = pat_bindings. clone ( ) ;
3843+ } else {
3844+ rib. bindings . extend ( pat_bindings. clone ( ) ) ;
3845+ }
3846+ if stop {
3847+ break ;
3848+ }
38073849 }
38083850 }
38093851
@@ -4675,6 +4717,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46754717 }
46764718
46774719 // Descend into the block.
4720+ for stmt in & block. stmts {
4721+ if let StmtKind :: Item ( ref item) = stmt. kind
4722+ && let ItemKind :: MacroDef ( ..) = item. kind
4723+ {
4724+ let res = self . r . local_def_id ( item. id ) . to_def_id ( ) ;
4725+ self . ribs [ ValueNS ] . push ( Rib :: new ( RibKind :: LookAheadMacroDefinition ( res) ) ) ;
4726+ }
4727+ }
4728+
46784729 for stmt in & block. stmts {
46794730 if let StmtKind :: Item ( ref item) = stmt. kind
46804731 && let ItemKind :: MacroDef ( ..) = item. kind
@@ -4691,6 +4742,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46914742 // Move back up.
46924743 self . parent_scope . module = orig_module;
46934744 for _ in 0 ..num_macro_definition_ribs {
4745+ // pop `LookAheadMacroDefinition` and `MacroDefinition`
4746+ self . ribs [ ValueNS ] . pop ( ) ;
46944747 self . ribs [ ValueNS ] . pop ( ) ;
46954748 self . label_ribs . pop ( ) ;
46964749 }
0 commit comments