Skip to content

Commit

Permalink
out_of_scope_macro_calls: Detect calls inside attributes more precisely
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Jul 6, 2024
1 parent 28cc0b6 commit 83cf471
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 12 deletions.
23 changes: 17 additions & 6 deletions compiler/rustc_resolve/src/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,25 @@ use rustc_hir::def_id::LocalDefId;
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(
resolver: &mut Resolver<'_, '_>,
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.
struct DefCollector<'a, 'b, 'tcx> {
resolver: &'a mut Resolver<'b, 'tcx>,
parent_def: LocalDefId,
impl_trait_context: ImplTraitContext,
in_attr: bool,
expansion: LocalExpnId,
}

Expand Down Expand Up @@ -53,7 +56,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
}

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;
}
Expand All @@ -63,7 +66,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
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;
}
Expand Down Expand Up @@ -105,8 +108,10 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {

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");
}
}
Expand Down Expand Up @@ -413,4 +418,10 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
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;
}
}
5 changes: 3 additions & 2 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -1371,7 +1371,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
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
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,12 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
.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,
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/macros/out-of-scope-calls-false-positives.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 83cf471

Please sign in to comment.