diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 68fbe48ebcb08..3e1e130822a3a 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -330,7 +330,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module = match rib.kind { RibKind::Module(module) => module, - RibKind::MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => { + RibKind::MacroDefinition(def) | RibKind::LookAheadMacroDefinition(def) + if def == self.macro_def(ident.span.ctxt()) => + { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. ident.span.remove_mark(); @@ -1141,6 +1143,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { | RibKind::FnOrCoroutine | RibKind::Module(..) | RibKind::MacroDefinition(..) + | RibKind::LookAheadMacroDefinition(..) | RibKind::ForwardGenericParamBan(_) => { // Nothing to do. Continue. } @@ -1233,6 +1236,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { | RibKind::FnOrCoroutine | RibKind::Module(..) | RibKind::MacroDefinition(..) + | RibKind::LookAheadMacroDefinition(..) | RibKind::InlineAsmSym | RibKind::AssocItem | RibKind::ForwardGenericParamBan(_) => { @@ -1326,6 +1330,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { | RibKind::FnOrCoroutine | RibKind::Module(..) | RibKind::MacroDefinition(..) + | RibKind::LookAheadMacroDefinition(..) | RibKind::InlineAsmSym | RibKind::AssocItem | RibKind::ForwardGenericParamBan(_) => continue, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ac7bdda41954e..a55ef1c3989b9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -103,7 +103,7 @@ impl IntoDiagArg for PatternSource { /// Denotes whether the context for the set of already bound bindings is a `Product` /// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`. /// See those functions for more information. -#[derive(PartialEq)] +#[derive(PartialEq, Debug)] enum PatBoundCtx { /// A product pattern context, e.g., `Variant(a, b)`. Product, @@ -217,6 +217,8 @@ pub(crate) enum RibKind<'ra> { /// We passed through a `macro_rules!` statement MacroDefinition(DefId), + LookAheadMacroDefinition(DefId), + /// All bindings in this rib are generic parameters that can't be used /// from the default of a generic parameter because they're not declared /// before said generic parameter. Also see the `visit_generics` override. @@ -247,6 +249,7 @@ impl RibKind<'_> { | RibKind::ConstantItem(..) | RibKind::Module(_) | RibKind::MacroDefinition(_) + | RibKind::LookAheadMacroDefinition(_) | RibKind::InlineAsmSym => false, RibKind::ConstParamTy | RibKind::AssocItem @@ -258,7 +261,9 @@ impl RibKind<'_> { /// This rib forbids referring to labels defined in upwards ribs. fn is_label_barrier(self) -> bool { match self { - RibKind::Normal | RibKind::MacroDefinition(..) => false, + RibKind::Normal + | RibKind::MacroDefinition(..) + | RibKind::LookAheadMacroDefinition(..) => false, RibKind::AssocItem | RibKind::FnOrCoroutine @@ -3793,17 +3798,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { /// Apply the bindings from a pattern to the innermost rib of the current scope. fn apply_pattern_bindings(&mut self, mut pat_bindings: PatternBindings) { - let rib_bindings = self.innermost_rib_bindings(ValueNS); let Some((_, pat_bindings)) = pat_bindings.pop() else { bug!("tried applying nonexistent bindings from pattern"); }; - - if rib_bindings.is_empty() { - // Often, such as for match arms, the bindings are introduced into a new rib. - // In this case, we can move the bindings over directly. - *rib_bindings = pat_bindings; - } else { - rib_bindings.extend(pat_bindings); + for rib in self.ribs[ValueNS].iter_mut().rev() { + let stop = !matches!(rib.kind, RibKind::LookAheadMacroDefinition(_)); + if rib.bindings.is_empty() { + // Often, such as for match arms, the bindings are introduced into a new rib. + // In this case, we can move the bindings over directly. + rib.bindings = pat_bindings.clone(); + } else { + rib.bindings.extend(pat_bindings.clone()); + } + if stop { + break; + } } } @@ -4680,11 +4689,19 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { && let ItemKind::MacroDef(..) = item.kind { num_macro_definition_ribs += 1; + let res = self.r.local_def_id(item.id).to_def_id(); + self.ribs[ValueNS].push(Rib::new(RibKind::LookAheadMacroDefinition(res))); + } + } + + for stmt in &block.stmts { + if let StmtKind::Item(ref item) = stmt.kind + && let ItemKind::MacroDef(..) = item.kind + { let res = self.r.local_def_id(item.id).to_def_id(); self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res))); self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res))); } - self.visit_stmt(stmt); } @@ -4694,6 +4711,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.ribs[ValueNS].pop(); self.label_ribs.pop(); } + for _ in 0..num_macro_definition_ribs { + // pop `RibKind::LookAheadMacroDefinition` + self.ribs[ValueNS].pop(); + } self.last_block_rib = self.ribs[ValueNS].pop(); if anonymous_module.is_some() { self.ribs[TypeNS].pop(); diff --git a/tests/ui/resolve/fresh-should-shallow-definitation-after-macro-expand.rs b/tests/ui/resolve/fresh-should-shallow-definitation-after-macro-expand.rs new file mode 100644 index 0000000000000..002c39667b9dd --- /dev/null +++ b/tests/ui/resolve/fresh-should-shallow-definitation-after-macro-expand.rs @@ -0,0 +1,46 @@ +//@ check-pass +//@ edition:2018 + +// issue#95237 + +fn f0() { + fn f() -> i8 { 42 } + let f = || -> i16 { 42 }; + + let a: i16 = m!(); + macro_rules! m {() => ( f() )} + use m; + let b: i16 = m!(); +} + +fn f1() { + fn f() -> i8 { 42 } + + let a: i8 = m!(); + let f = || -> i16 { 42 }; + macro_rules! m {() => ( f() )} + use m; + let b: i16 = m!(); +} + +fn f2() { + fn f() -> i8 { 42 } + + let a: i8 = m!(); + macro_rules! m {() => ( f() )} + use m; + let b: i8 = m!(); + + let f = || -> i16 { 42 }; +} + +fn f3() { + let f = || -> i16 { 42 }; + + let a: i16 = m!(); + macro_rules! m {() => ( f() )} + use m; + let b: i16 = m!(); +} + +fn main () {}