Skip to content

Commit 94fcccc

Browse files
committed
Auto merge of rust-lang#72529 - RalfJung:rollup-ydthv90, r=RalfJung
Rollup of 3 pull requests Successful merges: - rust-lang#72284 (Remove `macro_defs` map) - rust-lang#72393 (Rewrite `Parser::collect_tokens`) - rust-lang#72528 (Fix typo in doc comment.) Failed merges: r? @ghost
2 parents 7726070 + e2e3aac commit 94fcccc

File tree

11 files changed

+160
-95
lines changed

11 files changed

+160
-95
lines changed

src/librustc_ast_lowering/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
688688
) -> Span {
689689
span.fresh_expansion(ExpnData {
690690
allow_internal_unstable,
691-
..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition())
691+
..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition(), None)
692692
})
693693
}
694694

src/librustc_expand/base.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_data_structures::sync::{self, Lrc};
1313
use rustc_errors::{DiagnosticBuilder, ErrorReported};
1414
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
1515
use rustc_session::parse::ParseSess;
16+
use rustc_span::def_id::DefId;
1617
use rustc_span::edition::Edition;
1718
use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
1819
use rustc_span::source_map::SourceMap;
@@ -857,7 +858,13 @@ impl SyntaxExtension {
857858
SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr { mark_used }, edition)
858859
}
859860

860-
pub fn expn_data(&self, parent: ExpnId, call_site: Span, descr: Symbol) -> ExpnData {
861+
pub fn expn_data(
862+
&self,
863+
parent: ExpnId,
864+
call_site: Span,
865+
descr: Symbol,
866+
macro_def_id: Option<DefId>,
867+
) -> ExpnData {
861868
ExpnData {
862869
kind: ExpnKind::Macro(self.macro_kind(), descr),
863870
parent,
@@ -867,6 +874,7 @@ impl SyntaxExtension {
867874
allow_internal_unsafe: self.allow_internal_unsafe,
868875
local_inner_macros: self.local_inner_macros,
869876
edition: self.edition,
877+
macro_def_id,
870878
}
871879
}
872880
}

src/librustc_expand/expand.rs

+1
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
988988
ExpnKind::Macro(MacroKind::Attr, sym::derive),
989989
item.span(),
990990
self.cx.parse_sess.edition,
991+
None,
991992
)
992993
}),
993994
_ => None,

src/librustc_parse/parser/mod.rs

+113-73
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ impl<'a> Drop for Parser<'a> {
118118
struct TokenCursor {
119119
frame: TokenCursorFrame,
120120
stack: Vec<TokenCursorFrame>,
121+
cur_token: Option<TreeAndJoint>,
122+
collecting: Option<Collecting>,
121123
}
122124

123125
#[derive(Clone)]
@@ -127,30 +129,24 @@ struct TokenCursorFrame {
127129
open_delim: bool,
128130
tree_cursor: tokenstream::Cursor,
129131
close_delim: bool,
130-
last_token: LastToken,
131132
}
132133

133-
/// This is used in `TokenCursorFrame` above to track tokens that are consumed
134-
/// by the parser, and then that's transitively used to record the tokens that
135-
/// each parse AST item is created with.
136-
///
137-
/// Right now this has two states, either collecting tokens or not collecting
138-
/// tokens. If we're collecting tokens we just save everything off into a local
139-
/// `Vec`. This should eventually though likely save tokens from the original
140-
/// token stream and just use slicing of token streams to avoid creation of a
141-
/// whole new vector.
142-
///
143-
/// The second state is where we're passively not recording tokens, but the last
144-
/// token is still tracked for when we want to start recording tokens. This
145-
/// "last token" means that when we start recording tokens we'll want to ensure
146-
/// that this, the first token, is included in the output.
147-
///
148-
/// You can find some more example usage of this in the `collect_tokens` method
149-
/// on the parser.
150-
#[derive(Clone)]
151-
enum LastToken {
152-
Collecting(Vec<TreeAndJoint>),
153-
Was(Option<TreeAndJoint>),
134+
/// Used to track additional state needed by `collect_tokens`
135+
#[derive(Clone, Debug)]
136+
struct Collecting {
137+
/// Holds the current tokens captured during the most
138+
/// recent call to `collect_tokens`
139+
buf: Vec<TreeAndJoint>,
140+
/// The depth of the `TokenCursor` stack at the time
141+
/// collection was started. When we encounter a `TokenTree::Delimited`,
142+
/// we want to record the `TokenTree::Delimited` itself,
143+
/// but *not* any of the inner tokens while we are inside
144+
/// the new frame (this would cause us to record duplicate tokens).
145+
///
146+
/// This `depth` fields tracks stack depth we are recording tokens.
147+
/// Only tokens encountered at this depth will be recorded. See
148+
/// `TokenCursor::next` for more details.
149+
depth: usize,
154150
}
155151

156152
impl TokenCursorFrame {
@@ -161,7 +157,6 @@ impl TokenCursorFrame {
161157
open_delim: delim == token::NoDelim,
162158
tree_cursor: tts.clone().into_trees(),
163159
close_delim: delim == token::NoDelim,
164-
last_token: LastToken::Was(None),
165160
}
166161
}
167162
}
@@ -171,25 +166,38 @@ impl TokenCursor {
171166
loop {
172167
let tree = if !self.frame.open_delim {
173168
self.frame.open_delim = true;
174-
TokenTree::open_tt(self.frame.span, self.frame.delim)
175-
} else if let Some(tree) = self.frame.tree_cursor.next() {
169+
TokenTree::open_tt(self.frame.span, self.frame.delim).into()
170+
} else if let Some(tree) = self.frame.tree_cursor.next_with_joint() {
176171
tree
177172
} else if !self.frame.close_delim {
178173
self.frame.close_delim = true;
179-
TokenTree::close_tt(self.frame.span, self.frame.delim)
174+
TokenTree::close_tt(self.frame.span, self.frame.delim).into()
180175
} else if let Some(frame) = self.stack.pop() {
181176
self.frame = frame;
182177
continue;
183178
} else {
184179
return Token::new(token::Eof, DUMMY_SP);
185180
};
186181

187-
match self.frame.last_token {
188-
LastToken::Collecting(ref mut v) => v.push(tree.clone().into()),
189-
LastToken::Was(ref mut t) => *t = Some(tree.clone().into()),
182+
// Don't set an open delimiter as our current token - we want
183+
// to leave it as the full `TokenTree::Delimited` from the previous
184+
// iteration of this loop
185+
if !matches!(tree.0, TokenTree::Token(Token { kind: TokenKind::OpenDelim(_), .. })) {
186+
self.cur_token = Some(tree.clone());
187+
}
188+
189+
if let Some(collecting) = &mut self.collecting {
190+
if collecting.depth == self.stack.len() {
191+
debug!(
192+
"TokenCursor::next(): collected {:?} at depth {:?}",
193+
tree,
194+
self.stack.len()
195+
);
196+
collecting.buf.push(tree.clone().into())
197+
}
190198
}
191199

192-
match tree {
200+
match tree.0 {
193201
TokenTree::Token(token) => return token,
194202
TokenTree::Delimited(sp, delim, tts) => {
195203
let frame = TokenCursorFrame::new(sp, delim, &tts);
@@ -350,6 +358,8 @@ impl<'a> Parser<'a> {
350358
token_cursor: TokenCursor {
351359
frame: TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, &tokens),
352360
stack: Vec::new(),
361+
cur_token: None,
362+
collecting: None,
353363
},
354364
desugar_doc_comments,
355365
unmatched_angle_bracket_count: 0,
@@ -1105,65 +1115,95 @@ impl<'a> Parser<'a> {
11051115
}
11061116
}
11071117

1118+
/// Records all tokens consumed by the provided callback,
1119+
/// including the current token. These tokens are collected
1120+
/// into a `TokenStream`, and returned along with the result
1121+
/// of the callback.
1122+
///
1123+
/// Note: If your callback consumes an opening delimiter
1124+
/// (including the case where you call `collect_tokens`
1125+
/// when the current token is an opening delimeter),
1126+
/// you must also consume the corresponding closing delimiter.
1127+
///
1128+
/// That is, you can consume
1129+
/// `something ([{ }])` or `([{}])`, but not `([{}]`
1130+
///
1131+
/// This restriction shouldn't be an issue in practice,
1132+
/// since this function is used to record the tokens for
1133+
/// a parsed AST item, which always has matching delimiters.
11081134
fn collect_tokens<R>(
11091135
&mut self,
11101136
f: impl FnOnce(&mut Self) -> PResult<'a, R>,
11111137
) -> PResult<'a, (R, TokenStream)> {
11121138
// Record all tokens we parse when parsing this item.
1113-
let mut tokens = Vec::new();
1114-
let prev_collecting = match self.token_cursor.frame.last_token {
1115-
LastToken::Collecting(ref mut list) => Some(mem::take(list)),
1116-
LastToken::Was(ref mut last) => {
1117-
tokens.extend(last.take());
1118-
None
1119-
}
1120-
};
1121-
self.token_cursor.frame.last_token = LastToken::Collecting(tokens);
1122-
let prev = self.token_cursor.stack.len();
1139+
let tokens: Vec<TreeAndJoint> = self.token_cursor.cur_token.clone().into_iter().collect();
1140+
debug!("collect_tokens: starting with {:?}", tokens);
1141+
1142+
// We need special handling for the case where `collect_tokens` is called
1143+
// on an opening delimeter (e.g. '('). At this point, we have already pushed
1144+
// a new frame - however, we want to record the original `TokenTree::Delimited`,
1145+
// for consistency with the case where we start recording one token earlier.
1146+
// See `TokenCursor::next` to see how `cur_token` is set up.
1147+
let prev_depth =
1148+
if matches!(self.token_cursor.cur_token, Some((TokenTree::Delimited(..), _))) {
1149+
if self.token_cursor.stack.is_empty() {
1150+
// There is nothing below us in the stack that
1151+
// the function could consume, so the only thing it can legally
1152+
// capture is the entire contents of the current frame.
1153+
return Ok((f(self)?, TokenStream::new(tokens)));
1154+
}
1155+
// We have already recorded the full `TokenTree::Delimited` when we created
1156+
// our `tokens` vector at the start of this function. We are now inside
1157+
// a new frame corresponding to the `TokenTree::Delimited` we already recoreded.
1158+
// We don't want to record any of the tokens inside this frame, since they
1159+
// will be duplicates of the tokens nested inside the `TokenTree::Delimited`.
1160+
// Therefore, we set our recording depth to the *previous* frame. This allows
1161+
// us to record a sequence like: `(foo).bar()`: the `(foo)` will be recored
1162+
// as our initial `cur_token`, while the `.bar()` will be recored after we
1163+
// pop the `(foo)` frame.
1164+
self.token_cursor.stack.len() - 1
1165+
} else {
1166+
self.token_cursor.stack.len()
1167+
};
1168+
let prev_collecting =
1169+
self.token_cursor.collecting.replace(Collecting { buf: tokens, depth: prev_depth });
1170+
11231171
let ret = f(self);
1124-
let last_token = if self.token_cursor.stack.len() == prev {
1125-
&mut self.token_cursor.frame.last_token
1126-
} else if self.token_cursor.stack.get(prev).is_none() {
1127-
// This can happen due to a bad interaction of two unrelated recovery mechanisms with
1128-
// mismatched delimiters *and* recovery lookahead on the likely typo `pub ident(`
1129-
// (#62881).
1130-
return Ok((ret?, TokenStream::default()));
1172+
1173+
let mut collected_tokens = if let Some(collecting) = self.token_cursor.collecting.take() {
1174+
collecting.buf
11311175
} else {
1132-
&mut self.token_cursor.stack[prev].last_token
1176+
let msg = format!("our vector went away?");
1177+
debug!("collect_tokens: {}", msg);
1178+
self.sess.span_diagnostic.delay_span_bug(self.token.span, &msg);
1179+
// This can happen due to a bad interaction of two unrelated recovery mechanisms
1180+
// with mismatched delimiters *and* recovery lookahead on the likely typo
1181+
// `pub ident(` (#62895, different but similar to the case above).
1182+
return Ok((ret?, TokenStream::default()));
11331183
};
11341184

1135-
// Pull out the tokens that we've collected from the call to `f` above.
1136-
let mut collected_tokens = match *last_token {
1137-
LastToken::Collecting(ref mut v) => mem::take(v),
1138-
LastToken::Was(ref was) => {
1139-
let msg = format!("our vector went away? - found Was({:?})", was);
1140-
debug!("collect_tokens: {}", msg);
1141-
self.sess.span_diagnostic.delay_span_bug(self.token.span, &msg);
1142-
// This can happen due to a bad interaction of two unrelated recovery mechanisms
1143-
// with mismatched delimiters *and* recovery lookahead on the likely typo
1144-
// `pub ident(` (#62895, different but similar to the case above).
1145-
return Ok((ret?, TokenStream::default()));
1146-
}
1147-
};
1185+
debug!("collect_tokens: got raw tokens {:?}", collected_tokens);
11481186

11491187
// If we're not at EOF our current token wasn't actually consumed by
11501188
// `f`, but it'll still be in our list that we pulled out. In that case
11511189
// put it back.
11521190
let extra_token = if self.token != token::Eof { collected_tokens.pop() } else { None };
11531191

1154-
// If we were previously collecting tokens, then this was a recursive
1155-
// call. In that case we need to record all the tokens we collected in
1156-
// our parent list as well. To do that we push a clone of our stream
1157-
// onto the previous list.
1158-
match prev_collecting {
1159-
Some(mut list) => {
1160-
list.extend(collected_tokens.iter().cloned());
1161-
list.extend(extra_token);
1162-
*last_token = LastToken::Collecting(list);
1163-
}
1164-
None => {
1165-
*last_token = LastToken::Was(extra_token);
1192+
if let Some(mut collecting) = prev_collecting {
1193+
// If we were previously collecting at the same depth,
1194+
// then the previous call to `collect_tokens` needs to see
1195+
// the tokens we just recorded.
1196+
//
1197+
// If we were previously recording at an lower `depth`,
1198+
// then the previous `collect_tokens` call already recorded
1199+
// this entire frame in the form of a `TokenTree::Delimited`,
1200+
// so there is nothing else for us to do.
1201+
if collecting.depth == prev_depth {
1202+
collecting.buf.extend(collected_tokens.iter().cloned());
1203+
collecting.buf.extend(extra_token);
1204+
debug!("collect_tokens: updating previous buf to {:?}", collecting);
11661205
}
1206+
self.token_cursor.collecting = Some(collecting)
11671207
}
11681208

11691209
Ok((ret?, TokenStream::new(collected_tokens)))

src/librustc_resolve/build_reduced_graph.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ impl<'a> Resolver<'a> {
126126
}
127127

128128
crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
129-
let def_id = match self.macro_defs.get(&expn_id) {
130-
Some(def_id) => *def_id,
129+
let def_id = match expn_id.expn_data().macro_def_id {
130+
Some(def_id) => def_id,
131131
None => return self.ast_transform_scopes.get(&expn_id).unwrap_or(&self.graph_root),
132132
};
133133
if let Some(id) = self.definitions.as_local_node_id(def_id) {

src/librustc_resolve/lib.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,6 @@ pub struct Resolver<'a> {
922922
dummy_ext_bang: Lrc<SyntaxExtension>,
923923
dummy_ext_derive: Lrc<SyntaxExtension>,
924924
non_macro_attrs: [Lrc<SyntaxExtension>; 2],
925-
macro_defs: FxHashMap<ExpnId, DefId>,
926925
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
927926
ast_transform_scopes: FxHashMap<ExpnId, Module<'a>>,
928927
unused_macros: NodeMap<Span>,
@@ -1152,9 +1151,6 @@ impl<'a> Resolver<'a> {
11521151
let mut invocation_parent_scopes = FxHashMap::default();
11531152
invocation_parent_scopes.insert(ExpnId::root(), ParentScope::module(graph_root));
11541153

1155-
let mut macro_defs = FxHashMap::default();
1156-
macro_defs.insert(ExpnId::root(), root_def_id);
1157-
11581154
let features = session.features_untracked();
11591155
let non_macro_attr =
11601156
|mark_used| Lrc::new(SyntaxExtension::non_macro_attr(mark_used, session.edition()));
@@ -1229,7 +1225,6 @@ impl<'a> Resolver<'a> {
12291225
invocation_parent_scopes,
12301226
output_macro_rules_scopes: Default::default(),
12311227
helper_attrs: Default::default(),
1232-
macro_defs,
12331228
local_macro_def_scopes: FxHashMap::default(),
12341229
name_already_seen: FxHashMap::default(),
12351230
potentially_unused_imports: Vec::new(),
@@ -1335,8 +1330,8 @@ impl<'a> Resolver<'a> {
13351330

13361331
fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
13371332
loop {
1338-
match self.macro_defs.get(&ctxt.outer_expn()) {
1339-
Some(&def_id) => return def_id,
1333+
match ctxt.outer_expn().expn_data().macro_def_id {
1334+
Some(def_id) => return def_id,
13401335
None => ctxt.remove_mark(),
13411336
};
13421337
}
@@ -1820,7 +1815,7 @@ impl<'a> Resolver<'a> {
18201815
&& module.expansion.is_descendant_of(parent.expansion)
18211816
{
18221817
// The macro is a proc macro derive
1823-
if let Some(&def_id) = self.macro_defs.get(&module.expansion) {
1818+
if let Some(def_id) = module.expansion.expn_data().macro_def_id {
18241819
if let Some(ext) = self.get_macro_by_def_id(def_id) {
18251820
if !ext.is_builtin && ext.macro_kind() == MacroKind::Derive {
18261821
if parent.expansion.outer_expn_is_descendant_of(span.ctxt()) {

src/librustc_resolve/macros.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ impl<'a> base::Resolver for Resolver<'a> {
186186
call_site,
187187
self.session.edition(),
188188
features.into(),
189+
None,
189190
)));
190191

191192
let parent_scope = if let Some(module_id) = parent_module_id {
@@ -290,13 +291,17 @@ impl<'a> base::Resolver for Resolver<'a> {
290291
let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?;
291292

292293
let span = invoc.span();
293-
invoc_id.set_expn_data(ext.expn_data(parent_scope.expansion, span, fast_print_path(path)));
294-
295-
if let Res::Def(_, def_id) = res {
294+
invoc_id.set_expn_data(ext.expn_data(
295+
parent_scope.expansion,
296+
span,
297+
fast_print_path(path),
298+
res.opt_def_id(),
299+
));
300+
301+
if let Res::Def(_, _) = res {
296302
if after_derive {
297303
self.session.span_err(span, "macro attributes must be placed before `#[derive]`");
298304
}
299-
self.macro_defs.insert(invoc_id, def_id);
300305
let normal_module_def_id = self.macro_def_scope(invoc_id).normal_ancestor_id;
301306
self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
302307
}

0 commit comments

Comments
 (0)