@@ -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
@@ -3791,17 +3829,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37913829
37923830 /// Apply the bindings from a pattern to the innermost rib of the current scope.
37933831 fn apply_pattern_bindings ( & mut self , mut pat_bindings : PatternBindings ) {
3794- let rib_bindings = self . innermost_rib_bindings ( ValueNS ) ;
37953832 let Some ( ( _, pat_bindings) ) = pat_bindings. pop ( ) else {
37963833 bug ! ( "tried applying nonexistent bindings from pattern" ) ;
37973834 } ;
3798-
3799- if rib_bindings. is_empty ( ) {
3800- // Often, such as for match arms, the bindings are introduced into a new rib.
3801- // In this case, we can move the bindings over directly.
3802- * rib_bindings = pat_bindings;
3803- } else {
3804- rib_bindings. extend ( pat_bindings) ;
3835+ for rib in self . ribs [ ValueNS ] . iter_mut ( ) . rev ( ) {
3836+ let stop = !matches ! ( rib. kind, RibKind :: LookAheadMacroDefinition ( _) ) ;
3837+ if rib. bindings . is_empty ( ) {
3838+ // Often, such as for match arms, the bindings are introduced into a new rib.
3839+ // In this case, we can move the bindings over directly.
3840+ rib. bindings = pat_bindings. clone ( ) ;
3841+ } else {
3842+ rib. bindings . extend ( pat_bindings. clone ( ) ) ;
3843+ }
3844+ if stop {
3845+ break ;
3846+ }
38053847 }
38063848 }
38073849
@@ -4673,6 +4715,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46734715 }
46744716
46754717 // Descend into the block.
4718+ for stmt in & block. stmts {
4719+ if let StmtKind :: Item ( ref item) = stmt. kind
4720+ && let ItemKind :: MacroDef ( ..) = item. kind
4721+ {
4722+ let res = self . r . local_def_id ( item. id ) . to_def_id ( ) ;
4723+ self . ribs [ ValueNS ] . push ( Rib :: new ( RibKind :: LookAheadMacroDefinition ( res) ) ) ;
4724+ }
4725+ }
4726+
46764727 for stmt in & block. stmts {
46774728 if let StmtKind :: Item ( ref item) = stmt. kind
46784729 && let ItemKind :: MacroDef ( ..) = item. kind
@@ -4689,6 +4740,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46894740 // Move back up.
46904741 self . parent_scope . module = orig_module;
46914742 for _ in 0 ..num_macro_definition_ribs {
4743+ // pop `LookAheadMacroDefinition` and `MacroDefinition`
4744+ self . ribs [ ValueNS ] . pop ( ) ;
46924745 self . ribs [ ValueNS ] . pop ( ) ;
46934746 self . label_ribs . pop ( ) ;
46944747 }
0 commit comments