out_of_scope_macro_calls: Detect calls inside attributes more precisely
This commit is contained in:
parent
28cc0b643d
commit
83cf471361
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
10
tests/ui/macros/out-of-scope-calls-false-positives.rs
Normal file
10
tests/ui/macros/out-of-scope-calls-false-positives.rs
Normal 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() {}
|
Loading…
Reference in New Issue
Block a user