Auto merge of #87146 - Aaron1011:better-macro-lint, r=petrochenkov
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:
commit
0ecff8c623
13 changed files with 226 additions and 59 deletions
|
@ -120,6 +120,12 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
})
|
||||
}
|
||||
|
||||
fn visit_expr_field(&mut self, f: &'a ast::ExprField) {
|
||||
self.with_lint_attrs(f.id, &f.attrs, |cx| {
|
||||
ast_visit::walk_expr_field(cx, f);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, s: &'a ast::Stmt) {
|
||||
// Add the statement's lint attributes to our
|
||||
// current state when checking the statement itself.
|
||||
|
@ -204,8 +210,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_arm(&mut self, a: &'a ast::Arm) {
|
||||
run_early_pass!(self, check_arm, a);
|
||||
ast_visit::walk_arm(self, a);
|
||||
self.with_lint_attrs(a.id, &a.attrs, |cx| {
|
||||
run_early_pass!(cx, check_arm, a);
|
||||
ast_visit::walk_arm(cx, a);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_expr_post(&mut self, e: &'a ast::Expr) {
|
||||
|
@ -389,9 +397,15 @@ pub fn check_ast_crate<T: EarlyLintPass>(
|
|||
// All of the buffered lints should have been emitted at this point.
|
||||
// If not, that means that we somehow buffered a lint for a node id
|
||||
// that was not lint-checked (perhaps it doesn't exist?). This is a bug.
|
||||
for (_id, lints) in buffered.map {
|
||||
for (id, lints) in buffered.map {
|
||||
for early_lint in lints {
|
||||
sess.delay_span_bug(early_lint.span, "failed to process buffered lint here");
|
||||
sess.delay_span_bug(
|
||||
early_lint.span,
|
||||
&format!(
|
||||
"failed to process buffered lint here (dummy = {})",
|
||||
id == ast::DUMMY_NODE_ID
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue