diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index f75a625a279bb..000103ed5ede9 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -455,10 +455,9 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { fn block_needs_anonymous_module(&self, block: &Block) -> bool { // If any statements are items, we need to create an anonymous module - block - .stmts - .iter() - .any(|statement| matches!(statement.kind, StmtKind::Item(_) | StmtKind::MacCall(_))) + block.stmts.iter().any(|statement| { + matches!(statement.kind, StmtKind::Item(_) | StmtKind::MacCall(_) | StmtKind::Let(_)) + }) } // Add an import to the current module. diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index dae42645becdd..6182a8a277b33 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, CmResolver, Determinacy, - Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, - NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, - Resolver, Scope, ScopeSet, Segment, Stage, Used, Weak, errors, + Finalize, ImportKind, LexicalScopeBinding, LookaheadItemInBlock, Module, ModuleKind, + ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, + ResolutionError, Resolver, Scope, ScopeSet, Segment, Stage, Used, Weak, errors, }; #[derive(Copy, Clone)] @@ -328,20 +328,160 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { *original_rib_ident_def, ribs, ))); - } else if let RibKind::Block(Some(module)) = rib.kind - && let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(module), - ident, - ns, - parent_scope, - Shadowing::Unrestricted, - finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), - ignore_binding, - None, - ) - { - // The ident resolves to an item in a block. - return Some(LexicalScopeBinding::Item(binding)); + } else if let RibKind::Block { module, id: block_id } = rib.kind { + fn resolve_ident_in_forward_macro_of_block<'ra>( + r: &mut Resolver<'ra, '_>, + expansion: &mut Option, // macro_def_id + module: Module<'ra>, + resolving_block: NodeId, + ident: &mut Ident, + i: usize, + finalize: Option, + ribs: &[Rib<'ra>], + ) -> Option { + let items = r.lookahead_items_in_block.get(&resolving_block)?; + for (node_id, item) in items.iter().rev() { + match item { + LookaheadItemInBlock::MacroDef { def_id, bindings } => { + if *def_id != r.macro_def(ident.span.ctxt()) { + continue; + } + expansion.get_or_insert(*node_id); + ident.span.remove_mark(); + if let Some((original_rib_ident_def, (module_of_res, res))) = + bindings.get_key_value(ident) + && module_of_res.is_ancestor_of(module) + { + // The ident resolves to a type parameter or local variable. + return Some(r.validate_res_from_ribs( + i, + *ident, + *res, + finalize.map(|finalize| finalize.path_span), + *original_rib_ident_def, + ribs, + )); + } + } + LookaheadItemInBlock::Block => { + // resolve child block later + } + LookaheadItemInBlock::Binding { .. } => {} + } + } + + let subs = items + .iter() + .filter_map(|(node_id, item)| { + if matches!(item, LookaheadItemInBlock::Block) { + Some(*node_id) + } else { + None + } + }) + .collect::>(); + for node_id in subs { + if let Some(res) = resolve_ident_in_forward_macro_of_block( + r, expansion, module, node_id, ident, i, finalize, ribs, + ) { + return Some(res); + } + } + + None + } + + fn is_defined_later( + r: &Resolver<'_, '_>, + expansion: NodeId, // macro_def_id + block_id: NodeId, + ident: &Ident, + ) -> bool { + let Some(items) = r.lookahead_items_in_block.get(&block_id) else { + return false; + }; + for (node_id, item) in items { + match item { + LookaheadItemInBlock::Binding { name } => { + if name.name == ident.name { + return true; + } + } + LookaheadItemInBlock::Block => { + if is_defined_later(r, expansion, *node_id, ident) { + return true; + } + } + LookaheadItemInBlock::MacroDef { .. } => { + if expansion.eq(node_id) { + return false; + } + } + } + } + + false + } + + let mut expansion = None; + if let Some(res) = resolve_ident_in_forward_macro_of_block( + self, + &mut expansion, + parent_scope.module, + block_id, + &mut ident, + i, + finalize, + ribs, + ) { + return Some(LexicalScopeBinding::Res(res)); + } + + if let Some(expansion) = expansion + && is_defined_later(self, expansion, block_id, &ident) + { + // return `None` for this case: + // + // ``` + // let a = m!(); + // let b = 1; + // macro_rules! m { () => { b } } + // use b; + // ``` + return None; + } + + if let Some(module) = module + && let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted( + ModuleOrUniformRoot::Module(module), + ident, + ns, + parent_scope, + Shadowing::Unrestricted, + finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), + ignore_binding, + None, + ) + { + // The ident resolves to an item in a block. + if ns == TypeNS { + return Some(LexicalScopeBinding::Item(binding)); + } + let macro_def_id = self.macro_def(ident.span.ctxt()); + if !matches!(self.tcx.def_kind(macro_def_id), DefKind::Macro(_)) { + return Some(LexicalScopeBinding::Item(binding)); + } + return if binding + .span + .ctxt() + .outer_expn() + .outer_expn_is_descendant_of(ident.span.ctxt()) + { + Some(LexicalScopeBinding::Item(binding)) + } else { + None + }; + } } else if let RibKind::Module(module) = rib.kind { // Encountered a module item, abandon ribs and look into that module and preludes. let parent_scope = &ParentScope { module, ..*parent_scope }; @@ -1163,7 +1303,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for rib in ribs { match rib.kind { RibKind::Normal - | RibKind::Block(..) + | RibKind::Block { .. } | RibKind::FnOrCoroutine | RibKind::Module(..) | RibKind::MacroDefinition(..) @@ -1256,7 +1396,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::Block { .. } | RibKind::FnOrCoroutine | RibKind::Module(..) | RibKind::MacroDefinition(..) @@ -1350,7 +1490,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::Block { .. } | RibKind::FnOrCoroutine | RibKind::Module(..) | RibKind::MacroDefinition(..) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 679e663f88614..3a55d5c833fc6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -16,7 +16,7 @@ use rustc_ast::visit::{ AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, try_visit, visit_opt, walk_list, }; use rustc_ast::*; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{ @@ -39,9 +39,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; @@ -102,7 +102,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, @@ -197,7 +197,29 @@ pub(crate) enum RibKind<'ra> { /// `Block(None)` must be always processed in the same way as `Block(Some(module))` /// with empty `module`. The module can be `None` only because creation of some definitely /// empty modules is skipped as an optimization. - Block(Option>), + Block { + module: Option>, + /// The node id of block kind, which stores 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; + /// ``` + id: NodeId, + }, /// 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 @@ -249,7 +271,7 @@ impl RibKind<'_> { pub(crate) fn contains_params(&self) -> bool { match self { RibKind::Normal - | RibKind::Block(..) + | RibKind::Block { .. } | RibKind::FnOrCoroutine | RibKind::ConstantItem(..) | RibKind::Module(_) @@ -2816,7 +2838,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { for parent_rib in self.ribs[ns].iter().rev() { // Break at module or block level, to account for nested items which are // allowed to shadow generic param names. - if matches!(parent_rib.kind, RibKind::Module(..) | RibKind::Block(..)) { + if matches!(parent_rib.kind, RibKind::Module(..) | RibKind::Block { .. }) { break; } @@ -3765,10 +3787,101 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }); } + fn feed_macro_bindings_for_sub_block( + &self, + block_id: NodeId, + start: usize, + bindings: &PatternBindings, + // `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` + // } + // macro_rules! m2 {() => { x; }} // Injects `let x = 0` into `m2` + // ``` + need_removed: &mut FxIndexSet, + macro_bindings: &mut FxHashMap<(NodeId, NodeId, Ident), Res>, // (block_id, macro_def_id, Ident) -> Res + ) { + let Some(items) = self.r.lookahead_items_in_block.get(&block_id) else { + return; + }; + for (node_id, item) in items.iter().skip(start) { + match item { + LookaheadItemInBlock::Binding { name } => { + need_removed.insert(*name); + } + LookaheadItemInBlock::MacroDef { .. } => { + let bindings = bindings.last().unwrap().1.iter().filter_map(|(name, res)| { + if !need_removed.contains(name) { Some((*name, *res)) } else { None } + }); + for (name, res) in bindings { + let key = (block_id, *node_id, name); + macro_bindings.insert(key, res); + } + } + LookaheadItemInBlock::Block => { + let saved_len = need_removed.len(); + self.feed_macro_bindings_for_sub_block( + *node_id, + 0, + bindings, + need_removed, + macro_bindings, + ); + need_removed.truncate(saved_len); + } + } + } + } + /// Arising from `source`, resolve a top level pattern. 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, .. } = self.ribs[ValueNS].last_mut().unwrap().kind + && let Some(items) = self.r.lookahead_items_in_block.get(&id) + { + let start = items.get_index_of(&last_pat_id).unwrap_or_else(|| { + panic!("pattern({pat:#?}) not found in lookahead items"); + }); + let mut need_removed = FxIndexSet::default(); + let mut extend_bindings = FxHashMap::default(); + self.feed_macro_bindings_for_sub_block( + id, + start + 1, + &bindings, + &mut need_removed, + &mut extend_bindings, + ); + // We don't care the order here + #[allow(rustc::potential_query_instability)] + for ((block_id, macro_def_id, ident), res) in extend_bindings { + let Some(LookaheadItemInBlock::MacroDef { bindings: macro_bindings, .. }) = self + .r + .lookahead_items_in_block + .get_mut(&block_id) + .and_then(|block| block.get_mut(¯o_def_id)) + else { + unreachable!() + }; + macro_bindings.insert(ident, (self.parent_scope.module, res)); + } + } + self.apply_pattern_bindings(bindings); } @@ -4650,11 +4763,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let mut num_macro_definition_ribs = 0; if let Some(anonymous_module) = anonymous_module { debug!("(resolving block) found anonymous module, moving down"); - self.ribs[ValueNS].push(Rib::new(RibKind::Block(Some(anonymous_module)))); - self.ribs[TypeNS].push(Rib::new(RibKind::Block(Some(anonymous_module)))); + let rib_kind = RibKind::Block { module: Some(anonymous_module), id: block.id }; + self.ribs[ValueNS].push(Rib::new(rib_kind)); + self.ribs[TypeNS].push(Rib::new(rib_kind)); self.parent_scope.module = anonymous_module; } else { - self.ribs[ValueNS].push(Rib::new(RibKind::Block(None))); + self.ribs[ValueNS].push(Rib::new(RibKind::Block { module: None, id: block.id })); } // Descend into the block. @@ -4664,7 +4778,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))); } @@ -4674,7 +4787,7 @@ 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(); @@ -5134,6 +5247,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<'_, '_, '_> { @@ -5189,12 +5303,20 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } } } - + ItemKind::MacroDef(_, _) => { + if let Some(current_block) = self.current_block { + let def_id = self.r.local_def_id(item.id).to_def_id(); + let items = self.r.lookahead_items_in_block.entry(current_block).or_default(); + items.insert( + item.id, + LookaheadItemInBlock::MacroDef { bindings: Default::default(), def_id }, + ); + } + } ItemKind::Mod(..) | ItemKind::Static(..) | ItemKind::Use(..) | ItemKind::ExternCrate(..) - | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) | ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {} @@ -5205,7 +5327,9 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { // but for delegation items we are never actually retrieving that count in practice. } } - visit::walk_item(self, item) + let old_block = self.current_block.take(); + visit::walk_item(self, item); + self.current_block = old_block; } fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) { @@ -5214,11 +5338,34 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } visit::walk_assoc_item(self, item, ctxt); } + + fn visit_local(&mut self, node: &'ast Local) -> Self::Result { + // collect local bindings into block + node.pat.walk(&mut |pat| { + if let PatKind::Ident(_, name, _) = &pat.kind { + let current_block = self.current_block.unwrap(); + let items = self.r.lookahead_items_in_block.entry(current_block).or_default(); + items.insert(pat.id, LookaheadItemInBlock::Binding { name: *name }); + } + true + }); + visit::walk_local(self, node) + } + + fn visit_block(&mut self, node: &'ast Block) -> Self::Result { + if let Some(current_block) = self.current_block { + let items = self.r.lookahead_items_in_block.entry(current_block).or_default(); + items.insert(node.id, LookaheadItemInBlock::Block); + } + 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 80b2095d8ccff..50d7135d6e12e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -898,7 +898,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if path.len() == 1 { for rib in self.ribs[ns].iter().rev() { let item = path[0].ident; - if let RibKind::Module(module) | RibKind::Block(Some(module)) = rib.kind + if let RibKind::Module(module) | RibKind::Block { module: Some(module), .. } = + rib.kind && let Some(did) = find_doc_alias_name(self.r, module, item.name) { return Some((did, item)); @@ -2438,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. @@ -2456,7 +2457,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } - if let RibKind::Block(Some(module)) = rib.kind { + if let RibKind::Block { module: Some(module), .. } = rib.kind { self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt)); } else if let RibKind::Module(module) = rib.kind { // Encountered a module item, abandon ribs and look into that module and preludes. @@ -2470,14 +2471,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); break; } - - 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(); - } } } else { // Search in module. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 2afb52ef4d4be..d43fd07333ea9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1062,6 +1062,22 @@ pub struct ResolverOutputs { pub ast_lowering: ResolverAstLowering, } +#[derive(Debug)] +enum LookaheadItemInBlock<'ra> { + /// such as `let x = 1;` + Binding { name: Ident }, + /// such as `macro_rules! foo { ... }` + MacroDef { def_id: DefId, bindings: FxIndexMap, Res)> }, + /// block item in this block, such as: + /// ```ignore (illustrative) + /// { + /// { let x = 1 } + /// //~ ~ + /// } + /// ``` + Block, +} + /// The main resolver class. /// /// This is the visitor that walks the whole crate. @@ -1130,6 +1146,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. @@ -1657,6 +1674,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(), .. }; diff --git a/tests/ui/hygiene/auxiliary/legacy_interaction.rs b/tests/ui/hygiene/auxiliary/legacy_interaction.rs index 3293e346dadee..2b85ac1ff27a8 100644 --- a/tests/ui/hygiene/auxiliary/legacy_interaction.rs +++ b/tests/ui/hygiene/auxiliary/legacy_interaction.rs @@ -1,7 +1,7 @@ #[macro_export] macro_rules! m { () => { - fn f() {} // (2) - g(); // (1) + fn f() {} + g(); // g is not defined at macro definition site } } diff --git a/tests/ui/hygiene/auxiliary/unhygienic_example.rs b/tests/ui/hygiene/auxiliary/unhygienic_example.rs index 8e6e8f9b32f97..1138f162afa0d 100644 --- a/tests/ui/hygiene/auxiliary/unhygienic_example.rs +++ b/tests/ui/hygiene/auxiliary/unhygienic_example.rs @@ -14,7 +14,7 @@ macro_rules! unhygienic_macro { use my_crate::f; f(); - g(); // (3) unhygienic: `g` needs to be in scope at use site. + g(); // (3) hygienic: `g` resolves to (a) $crate::g(); // (4) hygienic: this always resolves to (a) } diff --git a/tests/ui/hygiene/legacy_interaction.rs b/tests/ui/hygiene/legacy_interaction.rs index 277650b545064..ec24ee9c488e3 100644 --- a/tests/ui/hygiene/legacy_interaction.rs +++ b/tests/ui/hygiene/legacy_interaction.rs @@ -1,4 +1,3 @@ -//@ check-pass #![allow(dead_code)] //@ aux-build:legacy_interaction.rs @@ -20,9 +19,9 @@ extern crate legacy_interaction; mod def_site { // Unless this macro opts out of hygiene, it should resolve the same wherever it is invoked. pub macro m2() { - ::legacy_interaction::m!(); + ::legacy_interaction::m!(); //~ ERROR cannot find function `g` in this scope f(); // This should resolve to (1) - fn g() {} // We want (2) resolve to this, not to (4) + fn g() {} } } diff --git a/tests/ui/hygiene/legacy_interaction.stderr b/tests/ui/hygiene/legacy_interaction.stderr new file mode 100644 index 0000000000000..e0c4d8f092879 --- /dev/null +++ b/tests/ui/hygiene/legacy_interaction.stderr @@ -0,0 +1,11 @@ +error[E0425]: cannot find function `g` in this scope + --> $DIR/legacy_interaction.rs:33:9 + | +LL | ::def_site::m2!(); + | ^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `::legacy_interaction::m` which comes from the expansion of the macro `::def_site::m2` (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 E0425`. diff --git a/tests/ui/hygiene/wrap_unhygienic_example.rs b/tests/ui/hygiene/wrap_unhygienic_example.rs index 6412117b2a6c7..52fdbf486c430 100644 --- a/tests/ui/hygiene/wrap_unhygienic_example.rs +++ b/tests/ui/hygiene/wrap_unhygienic_example.rs @@ -1,5 +1,3 @@ -//@ check-pass - //@ aux-build:my_crate.rs //@ aux-build:unhygienic_example.rs @@ -11,12 +9,12 @@ extern crate my_crate; // (b) // Hygienic version of `unhygienic_macro`. pub macro hygienic_macro() { fn g() {} // (c) - ::unhygienic_example::unhygienic_macro!(); + ::unhygienic_example::unhygienic_macro!(); //~ ERROR cannot find function `g` in this scope // ^ Even though we invoke an unhygienic macro, `hygienic_macro` remains hygienic. // In the above expansion: // (1) `my_crate` always resolves to (b) regardless of invocation site. // (2) The defined function `f` is only usable inside this macro definition. - // (3) `g` always resolves to (c) regardless of invocation site. + // (3) `g` remains hygienic and continues to resolve to (a). // (4) `$crate::g` remains hygienic and continues to resolve to (a). f(); diff --git a/tests/ui/hygiene/wrap_unhygienic_example.stderr b/tests/ui/hygiene/wrap_unhygienic_example.stderr new file mode 100644 index 0000000000000..d3b930bdaab34 --- /dev/null +++ b/tests/ui/hygiene/wrap_unhygienic_example.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find function `g` in this scope + --> $DIR/wrap_unhygienic_example.rs:25:5 + | +LL | hygienic_macro!(); + | ^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `::unhygienic_example::unhygienic_macro` which comes from the expansion of the macro `hygienic_macro` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider importing this function + | +LL + use unhygienic_example::g; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/hygiene/wrap_unhygienic_example2.rs b/tests/ui/hygiene/wrap_unhygienic_example2.rs new file mode 100644 index 0000000000000..57027abf454e6 --- /dev/null +++ b/tests/ui/hygiene/wrap_unhygienic_example2.rs @@ -0,0 +1,28 @@ +//@ check-pass + +//@ aux-build:my_crate.rs +//@ aux-build:unhygienic_example.rs + +#![feature(decl_macro)] + +extern crate unhygienic_example; +extern crate my_crate; // (b) + +use unhygienic_example::g; + +// Hygienic version of `unhygienic_macro`. +pub macro hygienic_macro() { + ::unhygienic_example::unhygienic_macro!(); + + f(); +} + +#[allow(unused)] +fn test_hygienic_macro() { + hygienic_macro!(); + + fn f() {} // (d) no conflict + f(); // resolves to (d) +} + +fn main() {} 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..4f15069ba5d85 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-decl-macro-expand.rs @@ -0,0 +1,99 @@ +//@ 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 } //~ NOTE you might have meant to refer to this function + 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 } //~ NOTE you might have meant to refer to this function + 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 } //~ NOTE you might have meant to refer to this function + //~| NOTE you might have meant to refer to this function + 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..aa6f2ea23d2a5 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-decl-macro-expand.stderr @@ -0,0 +1,58 @@ +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 +... +LL | fn f() -> FnF { 42 } + | - you might have meant to refer to this function + | + = 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 | fn f() -> FnF { 42 } + | - you might have meant to refer to this function +LL | let a2: BindingF = m!(); +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:56:17 + | +LL | let a0: BindingF = m!(); + | ---- in this macro invocation +LL | fn f() -> FnF { 42 } + | - you might have meant to refer to this function +... +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:56:17 + | +LL | fn f() -> FnF { 42 } + | - you might have meant to refer to this function +LL | +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..a3d75f28d71e3 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand-in-block.rs @@ -0,0 +1,272 @@ +//@ 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 ff0() { + // 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 ff1() { + // 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 ff2() { + // 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 ff3() { + // 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 ff4() { + // 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 ff5() { + // 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 ff6() { + // macro m6 -> let f -> fn f; + let a0: FnF = crate::m6!(); + { + #[macro_export] + macro_rules! m6 { () => { f() } } + let f = || -> BindingF { 42 }; + let a1: FnF = crate::m6!(); + } + let a2: FnF = crate::m6!(); + fn f() -> FnF { 42 } + let a3: FnF = crate::m6!(); +} + +fn f_with_macro_export0() { + { + let a: BindingF = 42; + let c0: BindingF = crate::m1!(); + { + { + { + { + let d0: BindingF = m1!(); + let d1: BindingF = crate::m1!(); + + #[macro_export] + macro_rules! m1 { () => { a } } //~ ERROR cannot find value `a` in this scope + //~| NOTE not found in this scope + use m1; + + let d2: BindingF = m1!(); + let d3: BindingF = crate::m1!(); + } + } + + let e0: BindingF = m0!(); + #[macro_export] + macro_rules! m0 { () => { a } } + use m0; + let e1: BindingF = m0!(); + } + } + let c1: BindingF = crate::m1!(); + } + crate::m1!(); //~ NOTE in this expansion of crate::m1! +} + +fn f_with_macro_export2() { + fn a() {}; + { + let a: BindingF = 42; + let c0: BindingF = crate::m2!(); + { + let d0: BindingF = m2!(); + let d1: BindingF = crate::m2!(); + #[macro_export] + macro_rules! m2 { () => { a } } //~ ERROR cannot find value `a` in this scope + //~| NOTE not found in this scope + use m2; + let d2: BindingF = m2!(); + let d3: BindingF = crate::m2!(); + } + let c1: BindingF = crate::m2!(); + } + crate::m2!(); //~ NOTE in this expansion of crate::m2! +} + +fn f_with_macro_export3() { + crate::m3!(); //~ NOTE in this expansion of crate::m3! + { + let a: BindingF = 42; + #[macro_export] + macro_rules! m3 { () => { a } } //~ ERROR cannot find value `a` in this scope + //~| ERROR cannot find value `a` in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + + } + crate::m3!(); //~ NOTE in this expansion of crate::m3! +} + +fn f_with_macro_export4() { + crate::m4!(); //~ NOTE in this expansion of crate::m4! + { + { + let a: BindingF = 42; + { + #[macro_export] + macro_rules! m4 { () => { a } } //~ ERROR cannot find value `a` in this scope + //~| ERROR cannot find value `a` in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + } + } + } + crate::m4!(); //~ NOTE in this expansion of crate::m4! +} + + +fn f_with_macro_export5() { + crate::m5!(); //~ NOTE in this expansion of crate::m5! + { + let a: BindingF = 42; + { + #[macro_export] + macro_rules! m5 { () => { a } } //~ ERROR cannot find value `a` in this scope + //~| ERROR cannot find value `a` in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + } + } + fn a() {}; + crate::m5!(); //~ NOTE in this expansion of crate::m5! +} + +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..f92dd34174b20 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand-in-block.stderr @@ -0,0 +1,135 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:183:51 + | +LL | macro_rules! m1 { () => { a } } + | ^ not found in this scope +... +LL | crate::m1!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `crate::m1` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:213:39 + | +LL | macro_rules! m2 { () => { a } } + | ^ not found in this scope +... +LL | crate::m2!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `crate::m2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:229:35 + | +LL | crate::m3!(); + | ------------ in this macro invocation +... +LL | macro_rules! m3 { () => { a } } + | ^ not found in this scope + | + = note: this error originates in the macro `crate::m3` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:229:35 + | +LL | macro_rules! m3 { () => { a } } + | ^ not found in this scope +... +LL | crate::m3!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `crate::m3` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:245:43 + | +LL | crate::m4!(); + | ------------ in this macro invocation +... +LL | macro_rules! m4 { () => { a } } + | ^ not found in this scope + | + = note: this error originates in the macro `crate::m4` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:245:43 + | +LL | macro_rules! m4 { () => { a } } + | ^ not found in this scope +... +LL | crate::m4!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `crate::m4` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:262:39 + | +LL | crate::m5!(); + | ------------ in this macro invocation +... +LL | macro_rules! m5 { () => { a } } + | ^ not found in this scope + | + = note: this error originates in the macro `crate::m5` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand-in-block.rs:262:39 + | +LL | macro_rules! m5 { () => { a } } + | ^ not found in this scope +... +LL | crate::m5!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `crate::m5` (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: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 12 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..49e9580b5fe9f --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand.rs @@ -0,0 +1,207 @@ +//@ edition:2018 + +// issue#95237 + +type FnF = i8; +type BindingF = i16; + +fn f_without_definition_f0() { + // let f -> macro m + let f = || -> BindingF { 42 }; + let a0: BindingF = m!(); + macro_rules! m {() => ( f() )} + use m; + let a1: BindingF = m!(); +} + +fn f_without_definition_f1() { + // macro m -> let f + let a: BindingF = m!(); //~ NOTE in this expansion of m! + macro_rules! m {() => ( f() )} //~ ERROR cannot find function `f` in this scope + //~| NOTE not found in this scope + use m; + let f = || -> BindingF { 42 }; +} + +fn f_without_closure_f0() { + // fn f -> macro f + fn f() -> FnF { 42 } + let a: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; +} + +fn f_without_closure_f1() { + // macro f -> fn f + let a: FnF = m!(); + macro_rules! m {() => ( f() )} + use m; + fn f() -> FnF { 42 } +} + +fn ff0() { + // 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 ff1() { + // 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 ff2() { + // 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 ff3() { + // 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 ff4() { + // 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 ff5() { + // 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 f_with_macro_export() { + let a: BindingF = 42; + + #[macro_export] + macro_rules! m4 { () => { a } } //~ ERROR cannot find value `a` in this scope + //~| ERROR cannot find value `a` in this scope + //~| ERROR cannot find value `a` in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + //~| NOTE not found in this scope + let b: BindingF = crate::m4!(); +} + +fn f_use_macro_export_1() { + fn a() {} + + crate::m4!(); //~ NOTE in this expansion of crate::m4! +} + +fn f_use_macro_export_2() { + crate::m4!(); //~ NOTE in this expansion of crate::m4! +} + +fn f_use_macro_export_3() { + let a = 42; + crate::m4!(); //~ NOTE in this expansion of crate::m4! +} + +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..bbd93d27dc3f5 --- /dev/null +++ b/tests/ui/resolve/fresh-should-shadow-definitation-in-macro-expand.stderr @@ -0,0 +1,134 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:183:31 + | +LL | macro_rules! m4 { () => { a } } + | ^ not found in this scope +... +LL | crate::m4!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `crate::m4` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:183:31 + | +LL | macro_rules! m4 { () => { a } } + | ^ not found in this scope +... +LL | crate::m4!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `crate::m4` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/fresh-should-shadow-definitation-in-macro-expand.rs:183:31 + | +LL | macro_rules! m4 { () => { a } } + | ^ not found in this scope +... +LL | crate::m4!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `crate::m4` (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:20:29 + | +LL | let a: 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:48: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:64: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:78: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:78: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:133: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:133: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:167: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:167: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 12 previous errors + +For more information about this error, try `rustc --explain E0425`.