out_of_scope_macro_calls: Detect calls inside attributes more precisely

This commit is contained in:
Vadim Petrochenkov 2024-06-26 13:00:51 +03:00
parent 28cc0b643d
commit 83cf471361
4 changed files with 35 additions and 12 deletions

View File

@ -8,6 +8,7 @@
use rustc_span::hygiene::LocalExpnId;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
use std::mem;
use tracing::debug;
pub(crate) fn collect_definitions(
@ -15,8 +16,9 @@ pub(crate) fn collect_definitions(
fragment: &AstFragment,
expansion: LocalExpnId,
) {
let (parent_def, impl_trait_context) = resolver.invocation_parents[&expansion];
fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion, impl_trait_context });
let (parent_def, impl_trait_context, in_attr) = resolver.invocation_parents[&expansion];
let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr };
fragment.visit_with(&mut visitor);
}
/// Creates `DefId`s for nodes in the AST.
@ -24,6 +26,7 @@ struct DefCollector<'a, 'b, 'tcx> {
resolver: &'a mut Resolver<'b, 'tcx>,
parent_def: LocalDefId,
impl_trait_context: ImplTraitContext,
in_attr: bool,
expansion: LocalExpnId,
}
@ -53,7 +56,7 @@ fn create_def(
}
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def);
let orig_parent_def = mem::replace(&mut self.parent_def, parent_def);
f(self);
self.parent_def = orig_parent_def;
}
@ -63,7 +66,7 @@ fn with_impl_trait<F: FnOnce(&mut Self)>(
impl_trait_context: ImplTraitContext,
f: F,
) {
let orig_itc = std::mem::replace(&mut self.impl_trait_context, impl_trait_context);
let orig_itc = mem::replace(&mut self.impl_trait_context, impl_trait_context);
f(self);
self.impl_trait_context = orig_itc;
}
@ -105,8 +108,10 @@ fn visit_anon_adt(&mut self, ty: &'a Ty) {
fn visit_macro_invoc(&mut self, id: NodeId) {
let id = id.placeholder_to_expn_id();
let old_parent =
self.resolver.invocation_parents.insert(id, (self.parent_def, self.impl_trait_context));
let old_parent = self
.resolver
.invocation_parents
.insert(id, (self.parent_def, self.impl_trait_context, self.in_attr));
assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
}
}
@ -413,4 +418,10 @@ fn visit_crate(&mut self, krate: &'a Crate) {
visit::walk_crate(self, krate)
}
}
fn visit_attribute(&mut self, attr: &'a Attribute) -> Self::Result {
let orig_in_attr = mem::replace(&mut self.in_attr, true);
visit::walk_attribute(self, attr);
self.in_attr = orig_in_attr;
}
}

View File

@ -1139,7 +1139,7 @@ pub struct Resolver<'a, 'tcx> {
/// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
/// we know what parent node that fragment should be attached to thanks to this table,
/// and how the `impl Trait` fragments were introduced.
invocation_parents: FxHashMap<LocalExpnId, (LocalDefId, ImplTraitContext)>,
invocation_parents: FxHashMap<LocalExpnId, (LocalDefId, ImplTraitContext, bool /*in_attr*/)>,
/// Some way to know that we are in a *trait* impl in `visit_assoc_item`.
/// FIXME: Replace with a more general AST map (together with some other fields).
@ -1371,7 +1371,8 @@ pub fn new(
node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed);
let mut invocation_parents = FxHashMap::default();
invocation_parents.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential));
invocation_parents
.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential, false));
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = tcx
.sess

View File

@ -297,11 +297,12 @@ fn resolve_macro_invocation(
.invocation_parents
.get(&invoc_id)
.or_else(|| self.invocation_parents.get(&eager_expansion_root))
.map(|&(mod_def_id, _)| mod_def_id)
.filter(|&mod_def_id| {
invoc.fragment_kind == AstFragmentKind::Expr
.filter(|&&(mod_def_id, _, in_attr)| {
in_attr
&& invoc.fragment_kind == AstFragmentKind::Expr
&& self.tcx.def_kind(mod_def_id) == DefKind::Mod
});
})
.map(|&(mod_def_id, ..)| mod_def_id);
let (ext, res) = self.smart_resolve_macro_path(
path,
kind,

View File

@ -0,0 +1,10 @@
//@ check-pass
//@ needs-asm-support
macro_rules! mac { () => { "" } }
macro_rules! mac2 { () => { "auxiliary/issue-40469.rs" } }
std::arch::global_asm!(mac!()); // OK
include!(mac2!()); // OK
fn main() {}