diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index f5bc46bf05304..71589646bd9ec 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -17,9 +17,9 @@ use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib use crate::macros::{MacroRulesScope, sub_namespace_match}; use crate::{ AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, Determinacy, Finalize, - ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, NameBinding, - NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, - ScopeSet, Segment, Used, Weak, errors, + ImportKind, LexicalScopeBinding, LookaheadItemInBlock, Module, ModuleKind, ModuleOrUniformRoot, + NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, + Resolver, Scope, ScopeSet, Segment, Used, Weak, errors, }; #[derive(Copy, Clone)] @@ -325,14 +325,60 @@ 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()) => { - // If an invocation of this macro created `ident`, give up on `ident` - // and switch to `ident`'s source from the macro definition. + if let RibKind::Block { id: block_id, .. } = &rib.kind + && let Some(items) = self.lookahead_items_in_block.get(block_id) + { + let mut expansion = None; + for (node_id, item) in items + .iter() + .rev() + .filter(|(_, item)| matches!(item, LookaheadItemInBlock::MacroDef { .. })) + { + let LookaheadItemInBlock::MacroDef { def_id, bindings, .. } = item else { + unreachable!(); + }; + if *def_id != self.macro_def(ident.span.ctxt()) { + continue; + } + expansion.get_or_insert(node_id); ident.span.remove_mark(); - continue; + if let Some((original_rib_ident_def, res)) = bindings.get_key_value(&ident) { + // The ident resolves to a type parameter or local variable. + return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs( + i, + ident, + *res, + finalize.map(|finalize| finalize.path_span), + *original_rib_ident_def, + ribs, + ))); + } } + if let Some(expansion) = expansion + && items.iter().take_while(|(item_id, _)| !expansion.eq(item_id)).any( + |(_, item)| { + if let LookaheadItemInBlock::Binding { name } = item { + name.name == ident.name + } else { + false + } + }, + ) + { + // return `None` for this case: + // + // ``` + // let a = m!(); + // let b = 1; + // macro_rules! m { () => { b } } + // use b; + // ``` + return None; + } + } + + module = match rib.kind { + RibKind::Module(module) => module, _ => continue, }; @@ -1147,6 +1193,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for rib in ribs { match rib.kind { RibKind::Normal + | RibKind::Block { .. } | RibKind::FnOrCoroutine | RibKind::Module(..) | RibKind::MacroDefinition(..) @@ -1239,6 +1286,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for rib in ribs { let (has_generic_params, def_kind) = match rib.kind { RibKind::Normal + | RibKind::Block { .. } | RibKind::FnOrCoroutine | RibKind::Module(..) | RibKind::MacroDefinition(..) @@ -1332,6 +1380,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for rib in ribs { let (has_generic_params, def_kind) = match rib.kind { RibKind::Normal + | RibKind::Block { .. } | RibKind::FnOrCoroutine | RibKind::Module(..) | RibKind::MacroDefinition(..) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 163e4b5b7a949..2cb11a60c8fbf 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -40,9 +40,9 @@ use thin_vec::ThinVec; use tracing::{debug, instrument, trace}; use crate::{ - BindingError, BindingKey, Finalize, LexicalScopeBinding, Module, ModuleOrUniformRoot, - NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, TyCtxt, UseError, - Used, errors, path_names_to_string, rustdoc, + BindingError, BindingKey, Finalize, LexicalScopeBinding, LookaheadItemInBlock, Module, + ModuleOrUniformRoot, NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, + TyCtxt, UseError, Used, errors, path_names_to_string, rustdoc, }; mod diagnostics; @@ -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, @@ -193,6 +193,27 @@ pub(crate) enum RibKind<'ra> { /// No restriction needs to be applied. Normal, + /// During resolving an item in a block, we had records all bindings defined + /// in this local scope, for these features: + /// + /// - Forward reference detection: + /// + /// ```ignore (illustrative) + /// let a = b; // displays '`b` is defined at ' instead of ''b' not found' + /// let b = 42; + /// ``` + /// + /// - Correctly resolves the hoisting bindings within macro expand: + /// + /// ```ignore (illustrative) + /// fn f() {} + /// let a: i16 = m!(); // throw error because it should use the local `f` rather than `fn f` + /// let f = || -> i16 { 42 }; + /// macro_rules! m {() => ( f() )} + /// use m; + /// ``` + Block { id: NodeId, is_module: bool }, + /// We passed through an impl or trait and are now in one of its /// methods or associated types. Allow references to ty params that impl or trait /// binds. Disallow any other upvars (including other ty params that are @@ -243,6 +264,7 @@ impl RibKind<'_> { pub(crate) fn contains_params(&self) -> bool { match self { RibKind::Normal + | RibKind::Block { .. } | RibKind::FnOrCoroutine | RibKind::ConstantItem(..) | RibKind::Module(_) @@ -258,7 +280,7 @@ 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::Block { .. } | RibKind::MacroDefinition(..) => false, RibKind::AssocItem | RibKind::FnOrCoroutine @@ -740,7 +762,7 @@ struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ribs: PerNS>>, /// Previous popped `rib`, only used for diagnostic. - last_block_rib: Option>, + last_normal_block_rib: Option>, /// The current set of local scopes, for labels. label_ribs: Vec>, @@ -1086,7 +1108,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc // Be sure not to set this until the function signature has been resolved. let previous_state = replace(&mut this.in_func_body, true); // We only care block in the same function - this.last_block_rib = None; + this.last_normal_block_rib = None; // Resolve the function body, potentially inside the body of an async closure this.with_lifetime_rib( LifetimeRibKind::Elided(LifetimeRes::Infer), @@ -1434,7 +1456,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { type_ns: vec![Rib::new(start_rib_kind)], macro_ns: vec![Rib::new(start_rib_kind)], }, - last_block_rib: None, + last_normal_block_rib: None, label_ribs: Vec::new(), lifetime_ribs: Vec::new(), lifetime_elision_candidates: None, @@ -2822,7 +2844,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { for parent_rib in self.ribs[ns].iter().rev() { // Break at mod level, to account for nested items which are // allowed to shadow generic param names. - if matches!(parent_rib.kind, RibKind::Module(..)) { + if matches!( + parent_rib.kind, + RibKind::Module(..) | RibKind::Block { is_module: true, .. } + ) { break; } @@ -3775,6 +3800,52 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) { let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; self.resolve_pattern(pat, pat_src, &mut bindings); + + let mut last_pat_id = None; + pat.walk(&mut |pat| { + if let PatKind::Ident(..) = pat.kind { + last_pat_id = Some(pat.id); + } + true + }); + + if let Some(last_pat_id) = last_pat_id + && let RibKind::Block { id: block, .. } = self.ribs[ValueNS].last_mut().unwrap().kind + && let Some(items) = self.r.lookahead_items_in_block.get_mut(&block) + { + let start = items.get_index_of(&last_pat_id).unwrap_or_else(|| { + panic!("pattern({pat:#?}) not found in lookahead items"); + }); + // let mut first_macro: Option = None; + // `need_removed` used for avoid injecting masked names into macro definition bindings: + // + // ``` + // let x = 0; + // macro_rules! m0 {() => { x; }} // Injects `let x = 0` into `m0` + // let x = 1; + // macro_rules! m1 {() => { x; }} // Should NOT inject `let x = 0` into `m1` + // ``` + let mut need_removed = FxHashSet::default(); + for (_, item) in items.iter_mut().skip(start + 1) { + match item { + LookaheadItemInBlock::Binding { name } => { + need_removed.insert(name.normalize_to_macro_rules()); + } + LookaheadItemInBlock::MacroDef { bindings: macro_bindings, .. } => { + let bindings = + bindings.last().unwrap().1.iter().filter_map(|(name, res)| { + if !need_removed.contains(&name) { + Some((*name, *res)) + } else { + None + } + }); + macro_bindings.extend(bindings); + } + } + } + } + self.apply_pattern_bindings(bindings); } @@ -4658,6 +4729,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Move down in the graph, if there's an anonymous module rooted here. let orig_module = self.parent_scope.module; let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference + let is_module_block = anonymous_module.is_some(); let mut num_macro_definition_ribs = 0; if let Some(anonymous_module) = anonymous_module { @@ -4669,6 +4741,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.ribs[ValueNS].push(Rib::new(RibKind::Normal)); } + self.ribs[ValueNS] + .push(Rib::new(RibKind::Block { id: block.id, is_module: is_module_block })); // Descend into the block. for stmt in &block.stmts { if let StmtKind::Item(ref item) = stmt.kind @@ -4676,7 +4750,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { { num_macro_definition_ribs += 1; 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))); } @@ -4686,10 +4759,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Move back up. self.parent_scope.module = orig_module; for _ in 0..num_macro_definition_ribs { - self.ribs[ValueNS].pop(); + // pop `MacroDefinition` self.label_ribs.pop(); } - self.last_block_rib = self.ribs[ValueNS].pop(); + let block_rib = self.ribs[ValueNS].pop(); // pop `RibKind::Block` + if !is_module_block { + self.last_normal_block_rib = block_rib; + } + self.ribs[ValueNS].pop(); // pop `RibKind::Module` or `RibKind::Normal` if anonymous_module.is_some() { self.ribs[TypeNS].pop(); } @@ -5146,6 +5223,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { /// lifetime generic parameters and function parameters. struct ItemInfoCollector<'a, 'ra, 'tcx> { r: &'a mut Resolver<'ra, 'tcx>, + current_block: Option, } impl ItemInfoCollector<'_, '_, '_> { @@ -5165,6 +5243,30 @@ impl ItemInfoCollector<'_, '_, '_> { }; self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig); } + + fn collect_fresh_binding(&mut self, binding: NodeId, name: Ident) { + let block_id = self.current_block.unwrap(); + let items = self.r.lookahead_items_in_block.entry(block_id).or_default(); + items.insert(binding, LookaheadItemInBlock::Binding { name }); + } + + fn collect_macro_def_in_block(&mut self, block_id: NodeId, node_id: NodeId) { + let def_id = self.r.local_def_id(node_id).to_def_id(); + let items = self.r.lookahead_items_in_block.entry(block_id).or_default(); + items.insert( + node_id, + LookaheadItemInBlock::MacroDef { bindings: Default::default(), def_id }, + ); + } + + fn collect_fresh_binding_in_pat(&mut self, pat: &ast::Pat) { + pat.walk(&mut |pat| { + if let PatKind::Ident(_, name, _) = &pat.kind { + self.collect_fresh_binding(pat.id, *name); + } + true + }); + } } impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { @@ -5201,12 +5303,15 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } } } - + ItemKind::MacroDef(_, _) => { + if let Some(block_id) = self.current_block { + self.collect_macro_def_in_block(block_id, item.id); + } + } ItemKind::Mod(..) | ItemKind::Static(..) | ItemKind::Use(..) | ItemKind::ExternCrate(..) - | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) | ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {} @@ -5226,11 +5331,22 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } visit::walk_assoc_item(self, item, ctxt); } + + fn visit_local(&mut self, node: &'ast Local) -> Self::Result { + self.collect_fresh_binding_in_pat(&node.pat); + visit::walk_local(self, node) + } + + fn visit_block(&mut self, node: &'ast Block) -> Self::Result { + let saved_block_id = self.current_block.replace(node.id); + visit::walk_block(self, node); + self.current_block = saved_block_id; + } } impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { - visit::walk_crate(&mut ItemInfoCollector { r: self }, krate); + visit::walk_crate(&mut ItemInfoCollector { r: self, current_block: None }, krate); let mut late_resolution_visitor = LateResolutionVisitor::new(self); late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c8ca57a380fef..554a4ba8b543e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -851,8 +851,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } // Try to find in last block rib - if let Some(rib) = &self.last_block_rib - && let RibKind::Normal = rib.kind + if let Some(rib) = &self.last_normal_block_rib + && let RibKind::Block { .. } = rib.kind { for (ident, &res) in &rib.bindings { if let Res::Local(_) = res @@ -2439,7 +2439,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ) -> TypoCandidate { let mut names = Vec::new(); if let [segment] = path { - let mut ctxt = segment.ident.span.ctxt(); + let ctxt = segment.ident.span.ctxt(); // Search in lexical scope. // Walk backwards up the ribs in scope and collect candidates. @@ -2457,15 +2457,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } - if let RibKind::MacroDefinition(def) = rib.kind - && def == self.r.macro_def(ctxt) - { - // If an invocation of this macro created `ident`, give up on `ident` - // and switch to `ident`'s source from the macro definition. - ctxt.remove_mark(); - continue; - } - // Items in scope if let RibKind::Module(module) = rib.kind { // Items from this module diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6b034c5129f39..224ade9c39d97 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1042,6 +1042,14 @@ pub struct ResolverOutputs { pub ast_lowering: ResolverAstLowering, } +#[derive(Debug)] +enum LookaheadItemInBlock { + /// such as `let x = 1;` + Binding { name: Ident }, + /// such as `macro_rules! foo { ... }` + MacroDef { def_id: DefId, bindings: FxIndexMap }, +} + /// The main resolver class. /// /// This is the visitor that walks the whole crate. @@ -1106,6 +1114,7 @@ pub struct Resolver<'ra, 'tcx> { /// There will be an anonymous module created around `g` with the ID of the /// entry block for `f`. block_map: NodeMap>, + lookahead_items_in_block: NodeMap>, /// A fake module that contains no definition and no prelude. Used so that /// some AST passes can generate identifiers that only resolve to local or /// lang items. @@ -1639,6 +1648,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { current_crate_outer_attr_insert_span, mods_with_parse_errors: Default::default(), impl_trait_names: Default::default(), + lookahead_items_in_block: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); diff --git a/tests/ui/resolve/binding-should-not-shadow-def-in-macro-expand.rs b/tests/ui/resolve/binding-should-not-shadow-def-in-macro-expand.rs new file mode 100644 index 0000000000000..71ae1592158e6 --- /dev/null +++ b/tests/ui/resolve/binding-should-not-shadow-def-in-macro-expand.rs @@ -0,0 +1,144 @@ +//@ edition:2018 + +type FnF = i8; +type BindingF = i16; + +fn main() {} + +fn f_without_definition_f(f: impl Fn() -> BindingF) { + // param f -> macro m + let a: BindingF = m!(); + macro_rules! m {() => ( f() )} + use m; +} + +fn fn0(f: impl Fn() -> BindingF) { + // param f -> fn f -> macro m + + let a0: FnF = m!(); + fn f() -> FnF { 42 } + let a1: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a2: FnF = m!(); +} + +fn fn1(f: impl Fn() -> BindingF) { + // param f -> macro m -> fn f + + let a0: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a1: FnF = m!(); + fn f() -> FnF { 42 } + let a2: FnF = m!(); +} + +fn closure() { + let c_without_definition_f = |f: BindingF| { + // param f -> macro m + let a1: BindingF = m!(); + macro_rules! m {() => ( f )} + use m; + }; + + let c0 = |f: BindingF| { + // param f -> fn f -> macro m + let a0: FnF = m!(); + fn f() -> FnF { 42 } + let a1: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a2: FnF = m!(); + }; + + let c1 = |f: BindingF| { + // param f -> macro m -> fn f + let a0: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a1: FnF = m!(); + fn f() -> FnF { 42 } + let a2: FnF = m!(); + }; +} + +fn for_loop() { + // for f -> macro m -> fn f + for f in 0..42 as BindingF { + let a0: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a1: FnF = m!(); + fn f() -> FnF { 42 } + let a2: FnF = m!(); + } + + // for f -> fn f -> macro m + for f in 0..42 as BindingF { + let a0: FnF = m!(); + fn f() -> FnF { 42 } + let a1: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a2: FnF = m!(); + } +} + +fn match_arm() { + // match f -> macro m -> fn f + match 42 as BindingF { + f => { + let a0: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a1: FnF = m!(); + fn f() -> FnF { 42 } + let a2: FnF = m!(); + } + } + + // match f -> fn f -> macro m + match 42 as BindingF { + f => { + let a0: FnF = m!(); + fn f() -> FnF { 42 } + let a1: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a2: FnF = m!(); + } + } +} + +fn let_in_if_expr() { + if let Some(f) = Some(|| -> BindingF { 42 }) { + // expr let f -> fn f -> macro f + let a0: FnF = m!(); + fn f() -> FnF { 42 } + let a1: FnF = m!(); + macro_rules! m {() => { f() };} + use m; + let a2: FnF = m!(); + } + + if let Some(f) = Some(|| -> BindingF { 42 }) { + // expr let f -> macro f -> fn f + let a0: FnF = m!(); + macro_rules! m {() => { f() };} + use m; + let a1: FnF = m!(); + fn f() -> FnF { 42 } + let a2: FnF = m!(); + } +} + +fn cannot_access_cross_fn() { + let f = || -> BindingF { 42 }; + fn g() { + macro_rules! m { + () => { f() }; //~ ERROR can't capture dynamic environment in a fn item + } + m!(); + } +} diff --git a/tests/ui/resolve/binding-should-not-shadow-def-in-macro-expand.stderr b/tests/ui/resolve/binding-should-not-shadow-def-in-macro-expand.stderr new file mode 100644 index 0000000000000..77e8955f89f8f --- /dev/null +++ b/tests/ui/resolve/binding-should-not-shadow-def-in-macro-expand.stderr @@ -0,0 +1,15 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/binding-should-not-shadow-def-in-macro-expand.rs:140:21 + | +LL | () => { f() }; + | ^ +LL | } +LL | m!(); + | ---- in this macro invocation + | + = help: use the `|| { ... }` closure form instead + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/resolve/fresh-should-shadow-definitation-in-decl-macro-expand.rs b/tests/ui/resolve/fresh-should-shadow-definitation-in-decl-macro-expand.rs new file mode 100644 index 0000000000000..0f4193f5d3c48 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-decl-macro-expand.rs @@ -0,0 +1,98 @@ +//@ edition:2018 +// issue#95237 + +#![feature(decl_macro)] + +type FnF = i8; +type BindingF = i16; + +fn f_without_definition_f() { + let f = || -> BindingF { 42 }; + let a: BindingF = m!(); + macro m() { f() } +} + +fn f_without_closure_f() { + fn f() -> FnF { 42 } + let a: FnF = m!(); + macro m() { f() } +} + +fn f0() { + // let f -> macro m -> fn f + + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + let f = || -> BindingF { 42 }; + let a1: BindingF = m!(); + macro m() { f() } //~ ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + let a2: BindingF = m!(); + fn f() -> FnF { 42 } + let a3: BindingF = m!(); +} + +fn f1() { + // let f -> fn f -> macro m + + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + let f = || -> BindingF { 42 }; + let a1: BindingF = m!(); + fn f() -> FnF { 42 } + let a2: BindingF = m!(); + macro m() { f() } //~ ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + let a3: BindingF = m!(); +} + +fn f2() { + // fn f -> let f -> macro m + + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + fn f() -> FnF { 42 } + let a1: BindingF = m!(); //~ NOTE in this expansion of m! + let f = || -> BindingF { 42 }; + let a2: BindingF = m!(); + macro m() { f() } //~ ERROR cannot find function `f` in this scope + //~| ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + let a3: BindingF = m!(); +} + +fn f3() { + // fn f -> macro m -> let f + + let a0: FnF = m!(); + fn f() -> FnF { 42 } + let a1: FnF = m!(); + macro m() { f() } + let a2: FnF = m!(); + let f = || -> BindingF { 42 }; + let a3: FnF = m!(); +} + +fn f4() { + // macro m -> fn f -> let f; + + let a0: FnF = m!(); + macro m() { f() } + let a1: FnF = m!(); + fn f() -> FnF { 42 } + let a2: FnF = m!(); + let f = || -> BindingF { 42 }; + let a3: FnF = m!(); +} + +fn f5() { + // macro m -> let f -> fn f; + + let a0: FnF = m!(); + macro m() { f() } + let a1: FnF = m!(); + let f = || -> BindingF { 42 }; + let a2: FnF = m!(); + fn f() -> FnF { 42 } + let a3: FnF = m!(); +} + +fn main () {} diff --git a/tests/ui/resolve/fresh-should-shadow-definitation-in-decl-macro-expand.stderr b/tests/ui/resolve/fresh-should-shadow-definitation-in-decl-macro-expand.stderr new file mode 100644 index 0000000000000..b51cc74d587c3 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-decl-macro-expand.stderr @@ -0,0 +1,47 @@ +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-decl-macro-expand.rs:27:17 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro m() { f() } + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-decl-macro-expand.rs:42:17 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro m() { f() } + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-decl-macro-expand.rs:55:17 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro m() { f() } + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-decl-macro-expand.rs:55:17 + | +LL | let a1: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro m() { f() } + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand-in-block.rs b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand-in-block.rs new file mode 100644 index 0000000000000..d8215c08d6560 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand-in-block.rs @@ -0,0 +1,157 @@ +//@ edition:2018 + +// issue#95237 + +type FnF = i8; +type BindingF = i16; + +fn b_without_definition_f() { + let f = || -> BindingF { 42 }; + { + let a: BindingF = m!(); + } + macro_rules! m {() => ( f() )} + use m; +} + +fn b_without_closure_f() { + fn f() -> FnF { 42 } + { + let a: FnF = m!(); + } + macro_rules! m {() => ( f() )} + use m; +} + +fn f0() { + // let f -> macro m -> fn f + + { + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + } + let f = || -> BindingF { 42 }; + { + let a1: BindingF = m!(); + } + macro_rules! m {() => ( f() )} //~ ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + use m; + { + let a2: BindingF = m!(); + } + fn f() -> FnF { 42 } + { + let a3: BindingF = m!(); + } +} + +fn f1() { + // let f -> fn f -> macro m + + { + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + } + let f = || -> BindingF { 42 }; + { + let a1: BindingF = m!(); + } + fn f() -> FnF { 42 } + { + let a2: BindingF = m!(); + } + macro_rules! m {() => ( f() )} //~ ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + use m; + { + let a3: BindingF = m!(); + } +} + +fn f2() { + // fn f -> let f -> macro m + + { + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + } + fn f() -> FnF { 42 } + { + let a1: BindingF = m!(); //~ NOTE in this expansion of m! + } + let f = || -> BindingF { 42 }; + { + let a2: BindingF = m!(); + } + macro_rules! m {() => ( f() )} //~ ERROR cannot find function `f` in this scope + //~| ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + use m; + { + let a3: BindingF = m!(); + } +} + +fn f3() { + // fn f -> macro m -> let f + + { + let a0: FnF = m!(); + } + fn f() -> FnF { 42 } + { + let a1: FnF = m!(); + } + macro_rules! m {() => ( f() )} + use m; + { + let a2: FnF = m!(); + } + let f = || -> BindingF { 42 }; + { + let a3: FnF = m!(); + } +} + +fn f4() { + // macro m -> fn f -> let f; + + { + let a0: FnF = m!(); + } + macro_rules! m {() => ( f() )} + use m; + { + let a1: FnF = m!(); + } + fn f() -> FnF { 42 } + { + let a2: FnF = m!(); + } + let f = || -> BindingF { 42 }; + { + let a3: FnF = m!(); + } +} + +fn f5() { + // macro m -> let f -> fn f; + + { + let a0: FnF = m!(); + } + macro_rules! m {() => ( f() )} + use m; + { + let a1: FnF = m!(); + } + let f = || -> BindingF { 42 }; + { + let a2: FnF = m!(); + } + fn f() -> FnF { 42 } + { + let a3: FnF = m!(); + } +} + +fn main () {} diff --git a/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand-in-block.stderr b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand-in-block.stderr new file mode 100644 index 0000000000000..a0e609f26b385 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand-in-block.stderr @@ -0,0 +1,47 @@ +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:36:29 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:62:29 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:84:29 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:84:29 + | +LL | let a1: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand.rs b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand.rs new file mode 100644 index 0000000000000..a07c5ef0f7a34 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand.rs @@ -0,0 +1,159 @@ +//@ edition:2018 + +// issue#95237 + +type FnF = i8; +type BindingF = i16; + +fn f_without_definition_f() { + let f = || -> BindingF { 42 }; + let a: BindingF = m!(); + macro_rules! m {() => ( f() )} + use m; +} + +fn f_without_closure_f0() { + fn f() -> FnF { 42 } + let a: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; +} + +fn f0() { + // let f -> macro m -> fn f + + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + let f = || -> BindingF { 42 }; + let a1: BindingF = m!(); + macro_rules! m {() => ( f() )} //~ ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + use m; + let a2: BindingF = m!(); + fn f() -> FnF { 42 } + let a3: BindingF = m!(); +} + +fn f1() { + // let f -> fn f -> macro m + + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + let f = || -> BindingF { 42 }; + let a1: BindingF = m!(); + fn f() -> FnF { 42 } + let a2: BindingF = m!(); + macro_rules! m {() => ( f() )} //~ ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + use m; + let a3: BindingF = m!(); +} + +fn f2() { + // fn f -> let f -> macro m + + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + fn f() -> FnF { 42 } + let a1: BindingF = m!(); //~ NOTE in this expansion of m! + let f = || -> BindingF { 42 }; + let a2: BindingF = m!(); + macro_rules! m {() => ( f() )} //~ ERROR cannot find function `f` in this scope + //~| ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + use m; + let a3: BindingF = m!(); +} + +fn f3() { + // fn f -> macro m -> let f + + let a0: FnF = m!(); + fn f() -> FnF { 42 } + let a1: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a2: FnF = m!(); + let f = || -> BindingF { 42 }; + let a3: FnF = m!(); +} + +fn f4() { + // macro m -> fn f -> let f; + + let a0: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a1: FnF = m!(); + fn f() -> FnF { 42 } + let a2: FnF = m!(); + let f = || -> BindingF { 42 }; + let a3: FnF = m!(); +} + +fn f5() { + // macro m -> let f -> fn f; + + let a0: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a1: FnF = m!(); + let f = || -> BindingF { 42 }; + let a2: FnF = m!(); + fn f() -> FnF { 42 } + let a3: FnF = m!(); +} + +fn tuple_f() { + // fn f -> let f in tuple -> macro m + + let a0: BindingF = m!(); //~ NOTE in this expansion of m! + fn f() -> FnF { 42 } + let a1: BindingF = m!(); //~ NOTE in this expansion of m! + let (f, _) = (|| -> BindingF { 42 }, ()); + let a2: BindingF = m!(); + macro_rules! m {() => ( f() )} //~ ERROR cannot find function `f` in this scope + //~| ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + use m; + let a3: BindingF = m!(); +} + +fn multiple() { + fn f() -> FnF { 42 } + let f = || -> BindingF { 42 }; + + let m0_0: BindingF = m0!(); + let m1_0: BindingF = m1!(); + let m2_0: i32 = m2!(); //~ NOTE in this expansion of m2! + + macro_rules! m0 { + () => { f() } + } + macro_rules! m1 { + () => { f() } + } + + let m0_1: BindingF = m0!(); + let m1_1: BindingF = m1!(); + let m2_1: i32 = m2!(); //~ NOTE in this expansion of m2! + + let f = || -> i32 { 42 }; + + let m0_2: BindingF = m0!(); + let m1_2: BindingF = m1!(); + let m2_2: i32 = m2!(); + + macro_rules! m2 { + () => { f() } //~ ERROR cannot find function `f` in this scope + } //~| ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + + let m0_3: BindingF = m0!(); + let m1_3: BindingF = m1!(); + let m2_3: i32 = m2!(); + + use {m0, m1, m2}; +} + +fn main () {} diff --git a/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand.stderr b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand.stderr new file mode 100644 index 0000000000000..98872d06da874 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand.stderr @@ -0,0 +1,91 @@ +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:28:29 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:44:29 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:58:29 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:58:29 + | +LL | let a1: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:113:29 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:113:29 + | +LL | let a1: BindingF = m!(); + | ---- in this macro invocation +... +LL | macro_rules! m {() => ( f() )} + | ^ not found in this scope + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:147:17 + | +LL | let m2_0: i32 = m2!(); + | ----- in this macro invocation +... +LL | () => { f() } + | ^ not found in this scope + | + = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:147:17 + | +LL | let m2_1: i32 = m2!(); + | ----- in this macro invocation +... +LL | () => { f() } + | ^ not found in this scope + | + = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0425`.