Skip to content

Commit 922ec17

Browse files
committed
Move jointness info from TokenStream to Token
Part of rust-lang#63689.
1 parent 5e3f1b1 commit 922ec17

File tree

13 files changed

+160
-156
lines changed

13 files changed

+160
-156
lines changed

src/librustc_ast/attr/mod.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::ast::{Path, PathSegment};
88
use crate::mut_visit::visit_clobber;
99
use crate::ptr::P;
1010
use crate::token::{self, CommentKind, Token};
11-
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
11+
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
1212

1313
use rustc_index::bit_set::GrowableBitSet;
1414
use rustc_span::source_map::{BytePos, Spanned};
@@ -362,17 +362,17 @@ pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
362362
}
363363

364364
impl MetaItem {
365-
fn token_trees_and_joints(&self) -> Vec<TreeAndJoint> {
365+
fn token_trees_and_joints(&self) -> Vec<TokenTree> {
366366
let mut idents = vec![];
367367
let mut last_pos = BytePos(0 as u32);
368368
for (i, segment) in self.path.segments.iter().enumerate() {
369369
let is_first = i == 0;
370370
if !is_first {
371371
let mod_sep_span =
372372
Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt());
373-
idents.push(TokenTree::token(token::ModSep, mod_sep_span).into());
373+
idents.push(TokenTree::token(token::ModSep, mod_sep_span));
374374
}
375-
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
375+
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)));
376376
last_pos = segment.ident.span.hi();
377377
}
378378
idents.extend(self.kind.token_trees_and_joints(self.span));
@@ -388,6 +388,7 @@ impl MetaItem {
388388
Some(TokenTree::Token(Token {
389389
kind: kind @ (token::Ident(..) | token::ModSep),
390390
span,
391+
spacing: _,
391392
})) => 'arm: {
392393
let mut segments = if let token::Ident(name, _) = kind {
393394
if let Some(TokenTree::Token(Token { kind: token::ModSep, .. })) = tokens.peek()
@@ -401,8 +402,11 @@ impl MetaItem {
401402
vec![PathSegment::path_root(span)]
402403
};
403404
loop {
404-
if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) =
405-
tokens.next().map(TokenTree::uninterpolate)
405+
if let Some(TokenTree::Token(Token {
406+
kind: token::Ident(name, _),
407+
span,
408+
spacing: _,
409+
})) = tokens.next().map(TokenTree::uninterpolate)
406410
{
407411
segments.push(PathSegment::from_ident(Ident::new(name, span)));
408412
} else {
@@ -459,7 +463,7 @@ impl MetaItemKind {
459463
}
460464
}
461465

462-
fn token_trees_and_joints(&self, span: Span) -> Vec<TreeAndJoint> {
466+
fn token_trees_and_joints(&self, span: Span) -> Vec<TokenTree> {
463467
match *self {
464468
MetaItemKind::Word => vec![],
465469
MetaItemKind::NameValue(ref lit) => {
@@ -554,7 +558,7 @@ impl NestedMetaItem {
554558
}
555559
}
556560

557-
fn token_trees_and_joints(&self) -> Vec<TreeAndJoint> {
561+
fn token_trees_and_joints(&self) -> Vec<TokenTree> {
558562
match *self {
559563
NestedMetaItem::MetaItem(ref item) => item.token_trees_and_joints(),
560564
NestedMetaItem::Literal(ref lit) => vec![lit.token_tree().into()],

src/librustc_ast/mut_visit.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -640,14 +640,14 @@ pub fn noop_visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
640640

641641
pub fn noop_visit_tts<T: MutVisitor>(TokenStream(tts): &mut TokenStream, vis: &mut T) {
642642
let tts = Lrc::make_mut(tts);
643-
visit_vec(tts, |(tree, _is_joint)| vis.visit_tt(tree));
643+
visit_vec(tts, |tree| vis.visit_tt(tree));
644644
}
645645

646646
// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
647647
// In practice the ident part is not actually used by specific visitors right now,
648648
// but there's a test below checking that it works.
649649
pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
650-
let Token { kind, span } = t;
650+
let Token { kind, span, spacing: _ } = t;
651651
match kind {
652652
token::Ident(name, _) | token::Lifetime(name) => {
653653
let mut ident = Ident::new(*name, *span);

src/librustc_ast/token.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,24 @@ pub enum TokenKind {
267267
#[cfg(target_arch = "x86_64")]
268268
rustc_data_structures::static_assert_size!(TokenKind, 16);
269269

270+
// FIXME: remove to Spacing, to match proc_macro
271+
#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
272+
pub enum Spacing {
273+
Alone,
274+
Joint,
275+
}
276+
270277
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
271278
pub struct Token {
272279
pub kind: TokenKind,
273280
pub span: Span,
281+
/// Is this operator token immediately followed by another operator token,
282+
/// without whitespace?
283+
///
284+
/// At the moment, this field is only used for proc_macros, and joint tokens
285+
/// are usually represented by dedicated token kinds. We want to transition
286+
/// to using jointness everywhere though (#63689).
287+
pub spacing: Spacing,
274288
}
275289

276290
impl TokenKind {
@@ -324,7 +338,11 @@ impl TokenKind {
324338

325339
impl Token {
326340
pub fn new(kind: TokenKind, span: Span) -> Self {
327-
Token { kind, span }
341+
Token::with_spacing(kind, span, Spacing::Alone)
342+
}
343+
344+
pub fn with_spacing(kind: TokenKind, span: Span, spacing: Spacing) -> Self {
345+
Token { kind, span, spacing }
328346
}
329347

330348
/// Some token that will be thrown away later.
@@ -622,6 +640,9 @@ impl Token {
622640
}
623641

624642
pub fn glue(&self, joint: &Token) -> Option<Token> {
643+
if self.spacing == Spacing::Alone {
644+
return None;
645+
}
625646
let kind = match self.kind {
626647
Eq => match joint.kind {
627648
Eq => EqEq,
@@ -678,7 +699,9 @@ impl Token {
678699
| Shebang(..) | Unknown(..) | Eof => return None,
679700
};
680701

681-
Some(Token::new(kind, self.span.to(joint.span)))
702+
let mut token = Token::new(kind, self.span.to(joint.span));
703+
token.spacing = joint.spacing;
704+
Some(token)
682705
}
683706
}
684707

@@ -709,7 +732,7 @@ pub enum Nonterminal {
709732

710733
// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
711734
#[cfg(target_arch = "x86_64")]
712-
rustc_data_structures::static_assert_size!(Nonterminal, 40);
735+
rustc_data_structures::static_assert_size!(Nonterminal, 48);
713736

714737
#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
715738
pub enum NonterminalKind {

src/librustc_ast/tokenstream.rs

+24-55
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
1414
//! ownership of the original.
1515
16-
use crate::token::{self, DelimToken, Token, TokenKind};
16+
use crate::token::{self, DelimToken, Spacing, Token, TokenKind};
1717

1818
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1919
use rustc_data_structures::sync::Lrc;
@@ -82,10 +82,6 @@ impl TokenTree {
8282
}
8383
}
8484

85-
pub fn joint(self) -> TokenStream {
86-
TokenStream::new(vec![(self, Joint)])
87-
}
88-
8985
pub fn token(kind: TokenKind, span: Span) -> TokenTree {
9086
TokenTree::Token(Token::new(kind, span))
9187
}
@@ -125,22 +121,12 @@ where
125121
/// instead of a representation of the abstract syntax tree.
126122
/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
127123
#[derive(Clone, Debug, Default, RustcEncodable, RustcDecodable)]
128-
pub struct TokenStream(pub Lrc<Vec<TreeAndJoint>>);
129-
130-
pub type TreeAndJoint = (TokenTree, IsJoint);
124+
pub struct TokenStream(pub Lrc<Vec<TokenTree>>);
131125

132126
// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
133127
#[cfg(target_arch = "x86_64")]
134128
rustc_data_structures::static_assert_size!(TokenStream, 8);
135129

136-
#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
137-
pub enum IsJoint {
138-
Joint,
139-
NonJoint,
140-
}
141-
142-
use IsJoint::*;
143-
144130
impl TokenStream {
145131
/// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
146132
/// separating the two arguments with a comma for diagnostic suggestions.
@@ -151,22 +137,22 @@ impl TokenStream {
151137
while let Some((pos, ts)) = iter.next() {
152138
if let Some((_, next)) = iter.peek() {
153139
let sp = match (&ts, &next) {
154-
(_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue,
140+
(_, TokenTree::Token(Token { kind: token::Comma, .. })) => continue,
155141
(
156-
(TokenTree::Token(token_left), NonJoint),
157-
(TokenTree::Token(token_right), _),
142+
TokenTree::Token(token_left @ Token { spacing: Spacing::Alone, .. }),
143+
TokenTree::Token(token_right),
158144
) if ((token_left.is_ident() && !token_left.is_reserved_ident())
159145
|| token_left.is_lit())
160146
&& ((token_right.is_ident() && !token_right.is_reserved_ident())
161147
|| token_right.is_lit()) =>
162148
{
163149
token_left.span
164150
}
165-
((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(),
151+
(TokenTree::Delimited(sp, ..), _) => sp.entire(),
166152
_ => continue,
167153
};
168154
let sp = sp.shrink_to_hi();
169-
let comma = (TokenTree::token(token::Comma, sp), NonJoint);
155+
let comma = TokenTree::token(token::Comma, sp);
170156
suggestion = Some((pos, comma, sp));
171157
}
172158
}
@@ -184,19 +170,13 @@ impl TokenStream {
184170

185171
impl From<TokenTree> for TokenStream {
186172
fn from(tree: TokenTree) -> TokenStream {
187-
TokenStream::new(vec![(tree, NonJoint)])
188-
}
189-
}
190-
191-
impl From<TokenTree> for TreeAndJoint {
192-
fn from(tree: TokenTree) -> TreeAndJoint {
193-
(tree, NonJoint)
173+
TokenStream::new(vec![(tree)])
194174
}
195175
}
196176

197177
impl iter::FromIterator<TokenTree> for TokenStream {
198178
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
199-
TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<TreeAndJoint>>())
179+
TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<TokenTree>>())
200180
}
201181
}
202182

@@ -209,7 +189,7 @@ impl PartialEq<TokenStream> for TokenStream {
209189
}
210190

211191
impl TokenStream {
212-
pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
192+
pub fn new(streams: Vec<TokenTree>) -> TokenStream {
213193
TokenStream(Lrc::new(streams))
214194
}
215195

@@ -224,8 +204,8 @@ impl TokenStream {
224204
pub fn span(&self) -> Option<Span> {
225205
match &**self.0 {
226206
[] => None,
227-
[(tt, _)] => Some(tt.span()),
228-
[(tt_start, _), .., (tt_end, _)] => Some(tt_start.span().to(tt_end.span())),
207+
[tt] => Some(tt.span()),
208+
[tt_start, .., tt_end] => Some(tt_start.span().to(tt_end.span())),
229209
}
230210
}
231211

@@ -290,18 +270,12 @@ impl TokenStream {
290270

291271
pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
292272
TokenStream(Lrc::new(
293-
self.0
294-
.iter()
295-
.enumerate()
296-
.map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint))
297-
.collect(),
273+
self.0.iter().enumerate().map(|(i, tree)| f(i, tree.clone())).collect(),
298274
))
299275
}
300276

301277
pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
302-
TokenStream(Lrc::new(
303-
self.0.iter().map(|(tree, is_joint)| (f(tree.clone()), *is_joint)).collect(),
304-
))
278+
TokenStream(Lrc::new(self.0.iter().map(|tree| f(tree.clone())).collect()))
305279
}
306280
}
307281

@@ -320,11 +294,11 @@ impl TokenStreamBuilder {
320294
// If `self` is not empty and the last tree within the last stream is a
321295
// token tree marked with `Joint`...
322296
if let Some(TokenStream(ref mut last_stream_lrc)) = self.0.last_mut() {
323-
if let Some((TokenTree::Token(last_token), Joint)) = last_stream_lrc.last() {
297+
if let Some(TokenTree::Token(last_token)) = last_stream_lrc.last() {
324298
// ...and `stream` is not empty and the first tree within it is
325299
// a token tree...
326300
let TokenStream(ref mut stream_lrc) = stream;
327-
if let Some((TokenTree::Token(token), is_joint)) = stream_lrc.first() {
301+
if let Some(TokenTree::Token(token)) = stream_lrc.first() {
328302
// ...and the two tokens can be glued together...
329303
if let Some(glued_tok) = last_token.glue(&token) {
330304
// ...then do so, by overwriting the last token
@@ -337,8 +311,7 @@ impl TokenStreamBuilder {
337311
// Overwrite the last token tree with the merged
338312
// token.
339313
let last_vec_mut = Lrc::make_mut(last_stream_lrc);
340-
*last_vec_mut.last_mut().unwrap() =
341-
(TokenTree::Token(glued_tok), *is_joint);
314+
*last_vec_mut.last_mut().unwrap() = TokenTree::Token(glued_tok);
342315

343316
// Remove the first token tree from `stream`. (This
344317
// is almost always the only tree in `stream`.)
@@ -375,23 +348,19 @@ impl Iterator for Cursor {
375348
type Item = TokenTree;
376349

377350
fn next(&mut self) -> Option<TokenTree> {
378-
self.next_with_joint().map(|(tree, _)| tree)
379-
}
380-
}
381-
382-
impl Cursor {
383-
fn new(stream: TokenStream) -> Self {
384-
Cursor { stream, index: 0 }
385-
}
386-
387-
pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
388351
if self.index < self.stream.len() {
389352
self.index += 1;
390353
Some(self.stream.0[self.index - 1].clone())
391354
} else {
392355
None
393356
}
394357
}
358+
}
359+
360+
impl Cursor {
361+
fn new(stream: TokenStream) -> Self {
362+
Cursor { stream, index: 0 }
363+
}
395364

396365
pub fn append(&mut self, new_stream: TokenStream) {
397366
if new_stream.is_empty() {
@@ -404,7 +373,7 @@ impl Cursor {
404373
}
405374

406375
pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
407-
self.stream.0[self.index..].get(n).map(|(tree, _)| tree.clone())
376+
self.stream.0[self.index..].get(n).cloned()
408377
}
409378
}
410379

0 commit comments

Comments
 (0)