Compute a better lint_node_id during expansion

When we need to emit a lint at a macro invocation, we currently use the
`NodeId` of its parent definition (e.g. the enclosing function). This
means that any `#[allow]` / `#[deny]` attributes placed 'closer' to the
macro (e.g. on an enclosing block or statement) will have no effect.

This commit computes a better `lint_node_id` in `InvocationCollector`.
When we visit/flat_map an AST node, we assign it a `NodeId` (earlier
than we normally would), and store than `NodeId` in current
`ExpansionData`. When we collect a macro invocation, the current
`lint_node_id` gets cloned along with our `ExpansionData`, allowing it
to be used if we need to emit a lint later on.

This improves the handling of `#[allow]` / `#[deny]` for
`SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` and some `asm!`-related lints.
The 'legacy derive helpers' lint retains its current behavior
(I've inlined the now-removed `lint_node_id` function), since
there isn't an `ExpansionData` readily available.
This commit is contained in:
Aaron Hill 2021-07-14 18:24:12 -05:00
parent eb0b95b55a
commit ddd544856e
No known key found for this signature in database
GPG key ID: B4087E510E98B164
10 changed files with 139 additions and 65 deletions

View file

@ -281,7 +281,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
// Derives are not included when `invocations` are collected, so we have to add them here.
let parent_scope = &ParentScope { derives, ..parent_scope };
let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion();
let node_id = self.lint_node_id(eager_expansion_root);
let node_id = invoc.expansion_data.lint_node_id;
let (ext, res) = self.smart_resolve_macro_path(
path,
kind,
@ -348,14 +348,6 @@ impl<'a> ResolverExpand for Resolver<'a> {
}
}
fn lint_node_id(&self, expn_id: LocalExpnId) -> NodeId {
// FIXME - make this more precise. This currently returns the NodeId of the
// nearest closing item - we should try to return the closest parent of the ExpnId
self.invocation_parents
.get(&expn_id)
.map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0])
}
fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool {
self.containers_deriving_copy.contains(&expn_id)
}
@ -1105,9 +1097,13 @@ impl<'a> Resolver<'a> {
let seg = Segment::from_ident(ident);
check_consistency(self, &[seg], ident.span, kind, initial_res, res);
if res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat) {
let node_id = self
.invocation_parents
.get(&parent_scope.expansion)
.map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]);
self.lint_buffer.buffer_lint_with_diagnostic(
LEGACY_DERIVE_HELPERS,
self.lint_node_id(parent_scope.expansion),
node_id,
ident.span,
"derive helper attribute is used before it is introduced",
BuiltinLintDiagnostics::LegacyDeriveHelpers(binding.span),