From 17d40c6057c88f4c432b0d7bac88e1b84cb7e67f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:03:36 +0200 Subject: Adding upstream version 1.65.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/syn/src/buffer.rs | 102 ++++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 36 deletions(-) (limited to 'vendor/syn/src/buffer.rs') diff --git a/vendor/syn/src/buffer.rs b/vendor/syn/src/buffer.rs index 2cb6690f0..2c8e21bdb 100644 --- a/vendor/syn/src/buffer.rs +++ b/vendor/syn/src/buffer.rs @@ -14,7 +14,9 @@ use crate::proc_macro as pm; use crate::Lifetime; use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::hint; use std::marker::PhantomData; +use std::mem; use std::ptr; use std::slice; @@ -57,29 +59,39 @@ impl TokenBuffer { // NOTE: Do not mutate the Vec returned from this function once it returns; // the address of its backing memory must remain stable. fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer { - // Build up the entries list, recording the locations of any Groups - // in the list to be processed later. - let mut entries = Vec::new(); - let mut groups = Vec::new(); - for tt in stream { + let iterator = stream.into_iter(); + let mut entries = Vec::with_capacity(iterator.size_hint().0 + 1); + let mut next_index_after_last_group = 0; + for tt in iterator { match tt { - TokenTree::Ident(sym) => { - entries.push(Entry::Ident(sym)); + TokenTree::Ident(ident) => { + entries.push(Entry::Ident(ident)); } - TokenTree::Punct(op) => { - entries.push(Entry::Punct(op)); + TokenTree::Punct(punct) => { + entries.push(Entry::Punct(punct)); } - TokenTree::Literal(l) => { - entries.push(Entry::Literal(l)); + TokenTree::Literal(literal) => { + entries.push(Entry::Literal(literal)); } - TokenTree::Group(g) => { - // Record the index of the interesting entry, and store an - // `End(null)` there temporarily. - groups.push((entries.len(), g)); - entries.push(Entry::End(ptr::null())); + TokenTree::Group(group) => { + // We cannot fill in a real `End` pointer until `entries` is + // finished growing and getting potentially reallocated. + // Instead, we temporarily coopt the spot where the end + // pointer would go, and use it to string together an + // intrusive linked list of all the Entry::Group entries in + // the vector. Later after `entries` is done growing, we'll + // traverse the linked list and fill in all the end + // pointers with a correct value. + let group_up = + ptr::null::().wrapping_add(next_index_after_last_group) as *const Entry; + + let inner = Self::inner_new(group.stream(), group_up); + entries.push(Entry::Group(group, inner)); + next_index_after_last_group = entries.len(); } } } + // Add an `End` entry to the end with a reference to the enclosing token // stream which was passed in. entries.push(Entry::End(up)); @@ -90,20 +102,36 @@ impl TokenBuffer { // pointer into it. let entries = entries.into_boxed_slice(); let len = entries.len(); + // Convert boxed slice into a pointer to the first element early, to // avoid invalidating pointers into this slice when we move the Box. // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326 let entries = Box::into_raw(entries) as *mut Entry; - for (idx, group) in groups { - // We know that this index refers to one of the temporary - // `End(null)` entries, and we know that the last entry is - // `End(up)`, so the next index is also valid. - let group_up = unsafe { entries.add(idx + 1) }; - - // The end entry stored at the end of this Entry::Group should - // point to the Entry which follows the Group in the list. - let inner = Self::inner_new(group.stream(), group_up); - unsafe { *entries.add(idx) = Entry::Group(group, inner) }; + + // Traverse intrusive linked list of Entry::Group entries and fill in + // correct End pointers. + while let Some(idx) = next_index_after_last_group.checked_sub(1) { + // We know that idx refers to one of the Entry::Group entries, and + // that the very last entry is an Entry::End, so the next index + // after any group entry is a valid index. + let group_up = unsafe { entries.add(next_index_after_last_group) }; + + // Linked list only takes us to entries which are of type Group. + let token_buffer = match unsafe { &*entries.add(idx) } { + Entry::Group(_group, token_buffer) => token_buffer, + _ => unsafe { hint::unreachable_unchecked() }, + }; + + // Last entry in any TokenBuffer is of type End. + let buffer_ptr = token_buffer.ptr as *mut Entry; + let last_entry = unsafe { &mut *buffer_ptr.add(token_buffer.len - 1) }; + let end_ptr_slot = match last_entry { + Entry::End(end_ptr_slot) => end_ptr_slot, + _ => unsafe { hint::unreachable_unchecked() }, + }; + + // Step to next element in linked list. + next_index_after_last_group = mem::replace(end_ptr_slot, group_up) as usize; } TokenBuffer { ptr: entries, len } @@ -275,7 +303,9 @@ impl<'a> Cursor<'a> { pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> { self.ignore_none(); match self.entry() { - Entry::Punct(op) if op.as_char() != '\'' => Some((op.clone(), unsafe { self.bump() })), + Entry::Punct(punct) if punct.as_char() != '\'' => { + Some((punct.clone(), unsafe { self.bump() })) + } _ => None, } } @@ -285,7 +315,7 @@ impl<'a> Cursor<'a> { pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> { self.ignore_none(); match self.entry() { - Entry::Literal(lit) => Some((lit.clone(), unsafe { self.bump() })), + Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump() })), _ => None, } } @@ -295,12 +325,12 @@ impl<'a> Cursor<'a> { pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> { self.ignore_none(); match self.entry() { - Entry::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => { + Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => { let next = unsafe { self.bump() }; match next.ident() { Some((ident, rest)) => { let lifetime = Lifetime { - apostrophe: op.span(), + apostrophe: punct.span(), ident, }; Some((lifetime, rest)) @@ -334,9 +364,9 @@ impl<'a> Cursor<'a> { pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> { let tree = match self.entry() { Entry::Group(group, _) => group.clone().into(), - Entry::Literal(lit) => lit.clone().into(), + Entry::Literal(literal) => literal.clone().into(), Entry::Ident(ident) => ident.clone().into(), - Entry::Punct(op) => op.clone().into(), + Entry::Punct(punct) => punct.clone().into(), Entry::End(..) => return None, }; @@ -348,9 +378,9 @@ impl<'a> Cursor<'a> { pub fn span(self) -> Span { match self.entry() { Entry::Group(group, _) => group.span(), - Entry::Literal(l) => l.span(), - Entry::Ident(t) => t.span(), - Entry::Punct(o) => o.span(), + Entry::Literal(literal) => literal.span(), + Entry::Ident(ident) => ident.span(), + Entry::Punct(punct) => punct.span(), Entry::End(..) => Span::call_site(), } } @@ -364,7 +394,7 @@ impl<'a> Cursor<'a> { Entry::End(..) => None, // Treat lifetimes as a single tt for the purposes of 'skip'. - Entry::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => { + Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => { let next = unsafe { self.bump() }; match next.entry() { Entry::Ident(_) => Some(unsafe { next.bump() }), -- cgit v1.2.3