Skip to content

Commit 217a745

Browse files
committed
expand: Give reasonable NodeIds to lints associated with macro definitions
1 parent 73d5cb0 commit 217a745

File tree

6 files changed

+36
-20
lines changed

6 files changed

+36
-20
lines changed

src/librustc_expand/mbe/macro_check.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
//! bound.
107107
use crate::mbe::{KleeneToken, TokenTree};
108108

109-
use rustc_ast::ast::NodeId;
109+
use rustc_ast::ast::{NodeId, DUMMY_NODE_ID};
110110
use rustc_ast::token::{DelimToken, Token, TokenKind};
111111
use rustc_data_structures::fx::FxHashMap;
112112
use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
@@ -626,5 +626,8 @@ fn ops_is_prefix(
626626
}
627627

628628
fn buffer_lint(sess: &ParseSess, span: MultiSpan, node_id: NodeId, message: &str) {
629-
sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message);
629+
// Macros loaded from other crates have dummy node ids.
630+
if node_id != DUMMY_NODE_ID {
631+
sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message);
632+
}
630633
}

src/librustc_expand/mbe/macro_parser.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
383383
}
384384
}
385385
TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => {
386-
if sess.missing_fragment_specifiers.borrow_mut().remove(&span) {
386+
if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
387387
return Err((span, "missing fragment specifier".to_string()));
388388
}
389389
}
@@ -566,7 +566,7 @@ fn inner_parse_loop<'root, 'tt>(
566566

567567
// We need to match a metavar (but the identifier is invalid)... this is an error
568568
TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => {
569-
if sess.missing_fragment_specifiers.borrow_mut().remove(&span) {
569+
if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
570570
return Error(span, "missing fragment specifier".to_string());
571571
}
572572
}

src/librustc_expand/mbe/macro_rules.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,9 @@ pub fn compile_declarative_macro(
474474
.map(|m| {
475475
if let MatchedNonterminal(ref nt) = *m {
476476
if let NtTT(ref tt) = **nt {
477-
let tt = mbe::quoted::parse(tt.clone().into(), true, sess).pop().unwrap();
477+
let tt = mbe::quoted::parse(tt.clone().into(), true, sess, def.id)
478+
.pop()
479+
.unwrap();
478480
valid &= check_lhs_nt_follows(sess, features, &def.attrs, &tt);
479481
return tt;
480482
}
@@ -491,7 +493,9 @@ pub fn compile_declarative_macro(
491493
.map(|m| {
492494
if let MatchedNonterminal(ref nt) = *m {
493495
if let NtTT(ref tt) = **nt {
494-
return mbe::quoted::parse(tt.clone().into(), false, sess).pop().unwrap();
496+
return mbe::quoted::parse(tt.clone().into(), false, sess, def.id)
497+
.pop()
498+
.unwrap();
495499
}
496500
}
497501
sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
@@ -509,9 +513,7 @@ pub fn compile_declarative_macro(
509513
valid &= check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
510514
}
511515

512-
// We use CRATE_NODE_ID instead of `def.id` otherwise we may emit buffered lints for a node id
513-
// that is not lint-checked and trigger the "failed to process buffered lint here" bug.
514-
valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses);
516+
valid &= macro_check::check_meta_variables(sess, def.id, def.span, &lhses, &rhses);
515517

516518
let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
517519
match transparency_error {

src/librustc_expand/mbe/quoted.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::mbe::macro_parser;
22
use crate::mbe::{Delimited, KleeneOp, KleeneToken, SequenceRepetition, TokenTree};
33

4+
use rustc_ast::ast::{NodeId, DUMMY_NODE_ID};
45
use rustc_ast::token::{self, Token};
56
use rustc_ast::tokenstream;
67
use rustc_ast_pretty::pprust;
@@ -36,6 +37,7 @@ pub(super) fn parse(
3637
input: tokenstream::TokenStream,
3738
expect_matchers: bool,
3839
sess: &ParseSess,
40+
node_id: NodeId,
3941
) -> Vec<TokenTree> {
4042
// Will contain the final collection of `self::TokenTree`
4143
let mut result = Vec::new();
@@ -46,7 +48,7 @@ pub(super) fn parse(
4648
while let Some(tree) = trees.next() {
4749
// Given the parsed tree, if there is a metavar and we are expecting matchers, actually
4850
// parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`).
49-
let tree = parse_tree(tree, &mut trees, expect_matchers, sess);
51+
let tree = parse_tree(tree, &mut trees, expect_matchers, sess, node_id);
5052
match tree {
5153
TokenTree::MetaVar(start_sp, ident) if expect_matchers => {
5254
let span = match trees.next() {
@@ -65,7 +67,10 @@ pub(super) fn parse(
6567
}
6668
tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp),
6769
};
68-
sess.missing_fragment_specifiers.borrow_mut().insert(span);
70+
if node_id != DUMMY_NODE_ID {
71+
// Macros loaded from other crates have dummy node ids.
72+
sess.missing_fragment_specifiers.borrow_mut().insert(span, node_id);
73+
}
6974
result.push(TokenTree::MetaVarDecl(span, ident, Ident::invalid()));
7075
}
7176

@@ -96,6 +101,7 @@ fn parse_tree(
96101
trees: &mut impl Iterator<Item = tokenstream::TokenTree>,
97102
expect_matchers: bool,
98103
sess: &ParseSess,
104+
node_id: NodeId,
99105
) -> TokenTree {
100106
// Depending on what `tree` is, we could be parsing different parts of a macro
101107
match tree {
@@ -111,7 +117,7 @@ fn parse_tree(
111117
sess.span_diagnostic.span_err(span.entire(), &msg);
112118
}
113119
// Parse the contents of the sequence itself
114-
let sequence = parse(tts, expect_matchers, sess);
120+
let sequence = parse(tts, expect_matchers, sess, node_id);
115121
// Get the Kleene operator and optional separator
116122
let (separator, kleene) = parse_sep_and_kleene_op(trees, span.entire(), sess);
117123
// Count the number of captured "names" (i.e., named metavars)
@@ -158,7 +164,7 @@ fn parse_tree(
158164
// descend into the delimited set and further parse it.
159165
tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
160166
span,
161-
Lrc::new(Delimited { delim, tts: parse(tts, expect_matchers, sess) }),
167+
Lrc::new(Delimited { delim, tts: parse(tts, expect_matchers, sess, node_id) }),
162168
),
163169
}
164170
}

src/librustc_interface/passes.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -307,16 +307,21 @@ fn configure_and_expand_inner<'a>(
307307
ecx.check_unused_macros();
308308
});
309309

310-
let mut missing_fragment_specifiers: Vec<_> =
311-
ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect();
312-
missing_fragment_specifiers.sort();
310+
let mut missing_fragment_specifiers: Vec<_> = ecx
311+
.parse_sess
312+
.missing_fragment_specifiers
313+
.borrow()
314+
.iter()
315+
.map(|(span, node_id)| (*span, *node_id))
316+
.collect();
317+
missing_fragment_specifiers.sort_unstable_by_key(|(span, _)| *span);
313318

314319
let recursion_limit_hit = ecx.reduced_recursion_limit.is_some();
315320

316-
for span in missing_fragment_specifiers {
321+
for (span, node_id) in missing_fragment_specifiers {
317322
let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER;
318323
let msg = "missing fragment specifier";
319-
resolver.lint_buffer().buffer_lint(lint, ast::CRATE_NODE_ID, span, msg);
324+
resolver.lint_buffer().buffer_lint(lint, node_id, span, msg);
320325
}
321326
if cfg!(windows) {
322327
env::set_var("PATH", &old_path);

src/librustc_session/parse.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ pub struct ParseSess {
119119
pub unstable_features: UnstableFeatures,
120120
pub config: CrateConfig,
121121
pub edition: Edition,
122-
pub missing_fragment_specifiers: Lock<FxHashSet<Span>>,
122+
pub missing_fragment_specifiers: Lock<FxHashMap<Span, NodeId>>,
123123
/// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
124124
pub raw_identifier_spans: Lock<Vec<Span>>,
125125
/// Used to determine and report recursive module inclusions.
@@ -150,7 +150,7 @@ impl ParseSess {
150150
unstable_features: UnstableFeatures::from_environment(),
151151
config: FxHashSet::default(),
152152
edition: ExpnId::root().expn_data().edition,
153-
missing_fragment_specifiers: Lock::new(FxHashSet::default()),
153+
missing_fragment_specifiers: Default::default(),
154154
raw_identifier_spans: Lock::new(Vec::new()),
155155
included_mod_stack: Lock::new(vec![]),
156156
source_map,

0 commit comments

Comments
 (0)