Skip to content

Commit 7285724

Browse files
committed
Make TokenStream use Option.
Because that's the more typical way of representing an all-or-nothing type.
1 parent ba31d83 commit 7285724

File tree

1 file changed

+45
-50
lines changed

1 file changed

+45
-50
lines changed

src/libsyntax/tokenstream.rs

+45-50
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,13 @@ impl TokenTree {
141141
/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
142142
/// instead of a representation of the abstract syntax tree.
143143
/// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat.
144+
///
145+
/// The use of `Option` is an optimization that avoids the need for an
146+
/// allocation when the stream is empty. However, it is not guaranteed that an
147+
/// empty stream is represented with `None`; it may be represented as a `Some`
148+
/// around an empty `Vec`.
144149
#[derive(Clone, Debug)]
145-
pub enum TokenStream {
146-
Empty,
147-
Stream(Lrc<Vec<TreeAndJoint>>),
148-
}
150+
pub struct TokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
149151

150152
pub type TreeAndJoint = (TokenTree, IsJoint);
151153

@@ -166,7 +168,7 @@ impl TokenStream {
166168
/// separating the two arguments with a comma for diagnostic suggestions.
167169
pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
168170
// Used to suggest if a user writes `foo!(a b);`
169-
if let TokenStream::Stream(ref stream) = self {
171+
if let Some(ref stream) = self.0 {
170172
let mut suggestion = None;
171173
let mut iter = stream.iter().enumerate().peekable();
172174
while let Some((pos, ts)) = iter.next() {
@@ -230,21 +232,21 @@ impl PartialEq<TokenStream> for TokenStream {
230232

231233
impl TokenStream {
232234
pub fn len(&self) -> usize {
233-
if let TokenStream::Stream(ref slice) = self {
235+
if let Some(ref slice) = self.0 {
234236
slice.len()
235237
} else {
236238
0
237239
}
238240
}
239241

240242
pub fn empty() -> TokenStream {
241-
TokenStream::Empty
243+
TokenStream(None)
242244
}
243245

244246
pub fn is_empty(&self) -> bool {
245-
match self {
246-
TokenStream::Empty => true,
247-
_ => false,
247+
match self.0 {
248+
None => true,
249+
Some(ref stream) => stream.is_empty(),
248250
}
249251
}
250252

@@ -255,9 +257,9 @@ impl TokenStream {
255257
_ => {
256258
let mut vec = vec![];
257259
for stream in streams {
258-
match stream {
259-
TokenStream::Empty => {},
260-
TokenStream::Stream(stream2) => vec.extend(stream2.iter().cloned()),
260+
match stream.0 {
261+
None => {},
262+
Some(stream2) => vec.extend(stream2.iter().cloned()),
261263
}
262264
}
263265
TokenStream::new(vec)
@@ -267,15 +269,14 @@ impl TokenStream {
267269

268270
pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
269271
match streams.len() {
270-
0 => TokenStream::empty(),
271-
_ => TokenStream::Stream(Lrc::new(streams)),
272+
0 => TokenStream(None),
273+
_ => TokenStream(Some(Lrc::new(streams))),
272274
}
273275
}
274276

275277
pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec<TreeAndJoint>) {
276-
match self {
277-
TokenStream::Empty => {}
278-
TokenStream::Stream(stream) => vec.extend(stream.iter().cloned()),
278+
if let Some(stream) = self.0 {
279+
vec.extend(stream.iter().cloned());
279280
}
280281
}
281282

@@ -340,41 +341,36 @@ impl TokenStream {
340341
}
341342

342343
pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
343-
match self {
344-
TokenStream::Empty => TokenStream::Empty,
345-
TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
344+
TokenStream(self.0.map(|stream| {
345+
Lrc::new(
346346
stream
347347
.iter()
348348
.enumerate()
349349
.map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint))
350-
.collect()
351-
)),
352-
}
350+
.collect())
351+
}))
353352
}
354353

355354
pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
356-
match self {
357-
TokenStream::Empty => TokenStream::Empty,
358-
TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
355+
TokenStream(self.0.map(|stream| {
356+
Lrc::new(
359357
stream
360358
.iter()
361359
.map(|(tree, is_joint)| (f(tree.clone()), *is_joint))
362-
.collect()
363-
)),
364-
}
360+
.collect())
361+
}))
365362
}
366363

367-
fn first_tree_and_joint(&self) -> Option<(TokenTree, IsJoint)> {
368-
match self {
369-
TokenStream::Empty => None,
370-
TokenStream::Stream(ref stream) => Some(stream.first().unwrap().clone())
371-
}
364+
fn first_tree_and_joint(&self) -> Option<TreeAndJoint> {
365+
self.0.as_ref().map(|stream| {
366+
stream.first().unwrap().clone()
367+
})
372368
}
373369

374370
fn last_tree_if_joint(&self) -> Option<TokenTree> {
375-
match self {
376-
TokenStream::Empty => None,
377-
TokenStream::Stream(ref stream) => {
371+
match self.0 {
372+
None => None,
373+
Some(ref stream) => {
378374
if let (tree, Joint) = stream.last().unwrap() {
379375
Some(tree.clone())
380376
} else {
@@ -418,21 +414,21 @@ impl TokenStreamBuilder {
418414
}
419415

420416
fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
421-
if let TokenStream::Stream(ref streams) = stream {
417+
if let Some(ref streams) = stream.0 {
422418
let len = streams.len();
423419
match len {
424420
1 => {}
425-
_ => self.0.push(TokenStream::Stream(Lrc::new(streams[0 .. len - 1].to_vec()))),
421+
_ => self.0.push(TokenStream(Some(Lrc::new(streams[0 .. len - 1].to_vec())))),
426422
}
427423
}
428424
}
429425

430426
fn push_all_but_first_tree(&mut self, stream: &TokenStream) {
431-
if let TokenStream::Stream(ref streams) = stream {
427+
if let Some(ref streams) = stream.0 {
432428
let len = streams.len();
433429
match len {
434430
1 => {}
435-
_ => self.0.push(TokenStream::Stream(Lrc::new(streams[1 .. len].to_vec()))),
431+
_ => self.0.push(TokenStream(Some(Lrc::new(streams[1 .. len].to_vec())))),
436432
}
437433
}
438434
}
@@ -458,9 +454,9 @@ impl Cursor {
458454
}
459455

460456
pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
461-
match self.stream {
462-
TokenStream::Empty => None,
463-
TokenStream::Stream(ref stream) => {
457+
match self.stream.0 {
458+
None => None,
459+
Some(ref stream) => {
464460
if self.index < stream.len() {
465461
self.index += 1;
466462
Some(stream[self.index - 1].clone())
@@ -476,16 +472,15 @@ impl Cursor {
476472
return;
477473
}
478474
let index = self.index;
479-
let stream = mem::replace(&mut self.stream, TokenStream::Empty);
475+
let stream = mem::replace(&mut self.stream, TokenStream(None));
480476
*self = TokenStream::from_streams(vec![stream, new_stream]).into_trees();
481477
self.index = index;
482478
}
483479

484480
pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
485-
match self.stream {
486-
TokenStream::Empty => None,
487-
TokenStream::Stream(ref stream) =>
488-
stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
481+
match self.stream.0 {
482+
None => None,
483+
Some(ref stream) => stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
489484
}
490485
}
491486
}

0 commit comments

Comments
 (0)