Upgrade proc-macro2 to 1.0.54 am: 9ed73418c7 am: aae936a18a am: 2873cb66cf am: 704d77a60e

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/proc-macro2/+/2514439

Change-Id: I415ef5359cac6c2d1c28eb4f12d5fc615d76438b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 3b65b55..9742e0b 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "bc369f088f1b4067bc08848e8c6060b51a00e9df"
+    "sha1": "9f9328b7f016d3f7782ee9443dc441d63abe5b09"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9d17e0c..3e1bbba 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -3,6 +3,7 @@
 on:
   push:
   pull_request:
+  workflow_dispatch:
   schedule: [cron: "40 1 * * *"]
 
 permissions:
@@ -51,9 +52,11 @@
     steps:
       - uses: actions/checkout@v3
       - uses: dtolnay/rust-toolchain@nightly
+      - name: Enable type layout randomization
+        run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV
       - run: cargo test
       - run: cargo test --no-default-features
-      - run: cargo test --no-default-features -- --ignored # run the ignored test to make sure the `proc-macro` feature is disabled
+      - run: cargo test --no-default-features --test features -- --ignored make_sure_no_proc_macro # run the ignored test to make sure the `proc-macro` feature is disabled
       - run: cargo test --features span-locations
       - run: cargo test --manifest-path tests/ui/Cargo.toml
       - name: RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
diff --git a/Android.bp b/Android.bp
index 50a5f59..9033168 100644
--- a/Android.bp
+++ b/Android.bp
@@ -41,7 +41,7 @@
     name: "libproc_macro2",
     crate_name: "proc_macro2",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.0.51",
+    cargo_pkg_version: "1.0.54",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
@@ -67,7 +67,7 @@
     name: "proc-macro2_test_defaults",
     crate_name: "proc_macro2",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.0.51",
+    cargo_pkg_version: "1.0.54",
     test_suites: ["general-tests"],
     auto_gen_config: true,
     edition: "2018",
@@ -87,6 +87,7 @@
         "libquote",
         "libunicode_ident",
     ],
+    proc_macros: ["librustversion"],
 }
 
 rust_test_host {
@@ -133,3 +134,12 @@
         unit_test: true,
     },
 }
+
+rust_test_host {
+    name: "proc-macro2_test_tests_test_size",
+    defaults: ["proc-macro2_test_defaults"],
+    srcs: ["tests/test_size.rs"],
+    test_options: {
+        unit_test: true,
+    },
+}
diff --git a/Cargo.toml b/Cargo.toml
index 092933e..f4269fd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 edition = "2018"
 rust-version = "1.31"
 name = "proc-macro2"
-version = "1.0.51"
+version = "1.0.54"
 authors = [
     "David Tolnay <dtolnay@gmail.com>",
     "Alex Crichton <alex@alexcrichton.com>",
@@ -56,6 +56,9 @@
 version = "1.0"
 default_features = false
 
+[dev-dependencies.rustversion]
+version = "1"
+
 [features]
 default = ["proc-macro"]
 nightly = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index d653e6f..385bf0f 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "proc-macro2"
-version = "1.0.51" # remember to update html_root_url
+version = "1.0.54" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>", "Alex Crichton <alex@alexcrichton.com>"]
 autobenches = false
 categories = ["development-tools::procedural-macro-helpers"]
@@ -25,6 +25,7 @@
 
 [dev-dependencies]
 quote = { version = "1.0", default_features = false }
+rustversion = "1"
 
 [features]
 proc-macro = []
diff --git a/METADATA b/METADATA
index 5d76bb6..cb301c8 100644
--- a/METADATA
+++ b/METADATA
@@ -11,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/proc-macro2/proc-macro2-1.0.51.crate"
+    value: "https://static.crates.io/crates/proc-macro2/proc-macro2-1.0.54.crate"
   }
-  version: "1.0.51"
+  version: "1.0.54"
   license_type: NOTICE
   last_upgrade_date {
     year: 2023
-    month: 2
-    day: 6
+    month: 3
+    day: 30
   }
 }
diff --git a/build.rs b/build.rs
index b69d813..59505a5 100644
--- a/build.rs
+++ b/build.rs
@@ -100,6 +100,10 @@
         println!("cargo:rustc-cfg=no_is_available");
     }
 
+    if version.minor < 66 {
+        println!("cargo:rustc-cfg=no_source_text");
+    }
+
     let target = env::var("TARGET").unwrap();
     if !enable_use_proc_macro(&target) {
         return;
diff --git a/src/extra.rs b/src/extra.rs
new file mode 100644
index 0000000..cbce162
--- /dev/null
+++ b/src/extra.rs
@@ -0,0 +1,100 @@
+//! Items which do not have a correspondence to any API in the proc_macro crate,
+//! but are necessary to include in proc-macro2.
+
+use crate::fallback;
+use crate::imp;
+use crate::marker::Marker;
+use crate::Span;
+use core::fmt::{self, Debug};
+
+/// An object that holds a [`Group`]'s `span_open()` and `span_close()` together
+/// (in a more compact representation than holding those 2 spans individually.
+///
+/// [`Group`]: crate::Group
+#[derive(Copy, Clone)]
+pub struct DelimSpan {
+    inner: DelimSpanEnum,
+    _marker: Marker,
+}
+
+#[derive(Copy, Clone)]
+enum DelimSpanEnum {
+    #[cfg(wrap_proc_macro)]
+    Compiler {
+        join: proc_macro::Span,
+        #[cfg(not(no_group_open_close))]
+        open: proc_macro::Span,
+        #[cfg(not(no_group_open_close))]
+        close: proc_macro::Span,
+    },
+    Fallback(fallback::Span),
+}
+
+impl DelimSpan {
+    pub(crate) fn new(group: &imp::Group) -> Self {
+        #[cfg(wrap_proc_macro)]
+        let inner = match group {
+            imp::Group::Compiler(group) => DelimSpanEnum::Compiler {
+                join: group.span(),
+                #[cfg(not(no_group_open_close))]
+                open: group.span_open(),
+                #[cfg(not(no_group_open_close))]
+                close: group.span_close(),
+            },
+            imp::Group::Fallback(group) => DelimSpanEnum::Fallback(group.span()),
+        };
+
+        #[cfg(not(wrap_proc_macro))]
+        let inner = DelimSpanEnum::Fallback(group.span());
+
+        DelimSpan {
+            inner,
+            _marker: Marker,
+        }
+    }
+
+    /// Returns a span covering the entire delimited group.
+    pub fn join(&self) -> Span {
+        match &self.inner {
+            #[cfg(wrap_proc_macro)]
+            DelimSpanEnum::Compiler { join, .. } => Span::_new(imp::Span::Compiler(*join)),
+            DelimSpanEnum::Fallback(span) => Span::_new_fallback(*span),
+        }
+    }
+
+    /// Returns a span for the opening punctuation of the group only.
+    pub fn open(&self) -> Span {
+        match &self.inner {
+            #[cfg(wrap_proc_macro)]
+            DelimSpanEnum::Compiler {
+                #[cfg(not(no_group_open_close))]
+                open,
+                #[cfg(no_group_open_close)]
+                    join: open,
+                ..
+            } => Span::_new(imp::Span::Compiler(*open)),
+            DelimSpanEnum::Fallback(span) => Span::_new_fallback(span.first_byte()),
+        }
+    }
+
+    /// Returns a span for the closing punctuation of the group only.
+    pub fn close(&self) -> Span {
+        match &self.inner {
+            #[cfg(wrap_proc_macro)]
+            DelimSpanEnum::Compiler {
+                #[cfg(not(no_group_open_close))]
+                close,
+                #[cfg(no_group_open_close)]
+                    join: close,
+                ..
+            } => Span::_new(imp::Span::Compiler(*close)),
+            DelimSpanEnum::Fallback(span) => Span::_new_fallback(span.last_byte()),
+        }
+    }
+}
+
+impl Debug for DelimSpan {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Debug::fmt(&self.join(), f)
+    }
+}
diff --git a/src/fallback.rs b/src/fallback.rs
index 587395d..29d3933 100644
--- a/src/fallback.rs
+++ b/src/fallback.rs
@@ -3,7 +3,7 @@
 use crate::parse::{self, Cursor};
 use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut};
 use crate::{Delimiter, Spacing, TokenTree};
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
 use core::cell::RefCell;
 #[cfg(span_locations)]
 use core::cmp;
@@ -13,8 +13,6 @@
 use core::ops::RangeBounds;
 use core::ptr;
 use core::str::FromStr;
-#[cfg(procmacro2_semver_exempt)]
-use std::path::Path;
 use std::path::PathBuf;
 
 /// Force use of proc-macro2's fallback implementation of the API for now, even
@@ -94,7 +92,7 @@
             if literal.repr.starts_with('-') {
                 push_negative_literal(vec, literal);
             } else {
-                vec.push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
+                vec.push(TokenTree::Literal(crate::Literal::_new_fallback(literal)));
             }
         }
         _ => vec.push(token),
@@ -104,9 +102,9 @@
     fn push_negative_literal(mut vec: RcVecMut<TokenTree>, mut literal: Literal) {
         literal.repr.remove(0);
         let mut punct = crate::Punct::new('-', Spacing::Alone);
-        punct.set_span(crate::Span::_new_stable(literal.span));
+        punct.set_span(crate::Span::_new_fallback(literal.span));
         vec.push(TokenTree::Punct(punct));
-        vec.push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
+        vec.push(TokenTree::Literal(crate::Literal::_new_fallback(literal)));
     }
 }
 
@@ -162,11 +160,14 @@
 
 #[cfg(span_locations)]
 fn get_cursor(src: &str) -> Cursor {
+    #[cfg(fuzzing)]
+    return Cursor { rest: src, off: 1 };
+
     // Create a dummy file & add it to the source map
+    #[cfg(not(fuzzing))]
     SOURCE_MAP.with(|cm| {
         let mut cm = cm.borrow_mut();
-        let name = format!("<parsed string {}>", cm.files.len());
-        let span = cm.add_file(&name, src);
+        let span = cm.add_file(src);
         Cursor {
             rest: src,
             off: span.lo,
@@ -334,29 +335,27 @@
     }
 }
 
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
 thread_local! {
     static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
         // NOTE: We start with a single dummy file which all call_site() and
         // def_site() spans reference.
         files: vec![FileInfo {
-            #[cfg(procmacro2_semver_exempt)]
-            name: "<unspecified>".to_owned(),
+            source_text: String::new(),
             span: Span { lo: 0, hi: 0 },
             lines: vec![0],
         }],
     });
 }
 
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
 struct FileInfo {
-    #[cfg(procmacro2_semver_exempt)]
-    name: String,
+    source_text: String,
     span: Span,
     lines: Vec<usize>,
 }
 
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
 impl FileInfo {
     fn offset_line_column(&self, offset: usize) -> LineColumn {
         assert!(self.span_within(Span {
@@ -379,11 +378,17 @@
     fn span_within(&self, span: Span) -> bool {
         span.lo >= self.span.lo && span.hi <= self.span.hi
     }
+
+    fn source_text(&self, span: Span) -> String {
+        let lo = (span.lo - self.span.lo) as usize;
+        let hi = (span.hi - self.span.lo) as usize;
+        self.source_text[lo..hi].to_owned()
+    }
 }
 
 /// Computes the offsets of each line in the given source string
 /// and the total number of characters
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
 fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
     let mut lines = vec![0];
     let mut total = 0;
@@ -398,12 +403,12 @@
     (total, lines)
 }
 
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
 struct SourceMap {
     files: Vec<FileInfo>,
 }
 
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
 impl SourceMap {
     fn next_start_pos(&self) -> u32 {
         // Add 1 so there's always space between files.
@@ -413,7 +418,7 @@
         self.files.last().unwrap().span.hi + 1
     }
 
-    fn add_file(&mut self, name: &str, src: &str) -> Span {
+    fn add_file(&mut self, src: &str) -> Span {
         let (len, lines) = lines_offsets(src);
         let lo = self.next_start_pos();
         // XXX(nika): Should we bother doing a checked cast or checked add here?
@@ -423,25 +428,35 @@
         };
 
         self.files.push(FileInfo {
-            #[cfg(procmacro2_semver_exempt)]
-            name: name.to_owned(),
+            source_text: src.to_owned(),
             span,
             lines,
         });
 
-        #[cfg(not(procmacro2_semver_exempt))]
-        let _ = name;
-
         span
     }
 
+    #[cfg(procmacro2_semver_exempt)]
+    fn filepath(&self, span: Span) -> PathBuf {
+        for (i, file) in self.files.iter().enumerate() {
+            if file.span_within(span) {
+                return PathBuf::from(if i == 0 {
+                    "<unspecified>".to_owned()
+                } else {
+                    format!("<parsed string {}>", i)
+                });
+            }
+        }
+        unreachable!("Invalid span with no related FileInfo!");
+    }
+
     fn fileinfo(&self, span: Span) -> &FileInfo {
         for file in &self.files {
             if file.span_within(span) {
                 return file;
             }
         }
-        panic!("Invalid span with no related FileInfo!");
+        unreachable!("Invalid span with no related FileInfo!");
     }
 }
 
@@ -487,17 +502,25 @@
 
     #[cfg(procmacro2_semver_exempt)]
     pub fn source_file(&self) -> SourceFile {
+        #[cfg(fuzzing)]
+        return SourceFile {
+            path: PathBuf::from("<unspecified>"),
+        };
+
+        #[cfg(not(fuzzing))]
         SOURCE_MAP.with(|cm| {
             let cm = cm.borrow();
-            let fi = cm.fileinfo(*self);
-            SourceFile {
-                path: Path::new(&fi.name).to_owned(),
-            }
+            let path = cm.filepath(*self);
+            SourceFile { path }
         })
     }
 
     #[cfg(span_locations)]
     pub fn start(&self) -> LineColumn {
+        #[cfg(fuzzing)]
+        return LineColumn { line: 0, column: 0 };
+
+        #[cfg(not(fuzzing))]
         SOURCE_MAP.with(|cm| {
             let cm = cm.borrow();
             let fi = cm.fileinfo(*self);
@@ -507,6 +530,10 @@
 
     #[cfg(span_locations)]
     pub fn end(&self) -> LineColumn {
+        #[cfg(fuzzing)]
+        return LineColumn { line: 0, column: 0 };
+
+        #[cfg(not(fuzzing))]
         SOURCE_MAP.with(|cm| {
             let cm = cm.borrow();
             let fi = cm.fileinfo(*self);
@@ -541,6 +568,13 @@
 
     #[cfg(span_locations)]
     pub fn join(&self, other: Span) -> Option<Span> {
+        #[cfg(fuzzing)]
+        return {
+            let _ = other;
+            None
+        };
+
+        #[cfg(not(fuzzing))]
         SOURCE_MAP.with(|cm| {
             let cm = cm.borrow();
             // If `other` is not within the same FileInfo as us, return None.
@@ -555,12 +589,32 @@
     }
 
     #[cfg(not(span_locations))]
-    fn first_byte(self) -> Self {
+    pub fn source_text(&self) -> Option<String> {
+        None
+    }
+
+    #[cfg(span_locations)]
+    pub fn source_text(&self) -> Option<String> {
+        #[cfg(fuzzing)]
+        return None;
+
+        #[cfg(not(fuzzing))]
+        {
+            if self.is_call_site() {
+                None
+            } else {
+                Some(SOURCE_MAP.with(|cm| cm.borrow().fileinfo(*self).source_text(*self)))
+            }
+        }
+    }
+
+    #[cfg(not(span_locations))]
+    pub(crate) fn first_byte(self) -> Self {
         self
     }
 
     #[cfg(span_locations)]
-    fn first_byte(self) -> Self {
+    pub(crate) fn first_byte(self) -> Self {
         Span {
             lo: self.lo,
             hi: cmp::min(self.lo.saturating_add(1), self.hi),
@@ -568,17 +622,22 @@
     }
 
     #[cfg(not(span_locations))]
-    fn last_byte(self) -> Self {
+    pub(crate) fn last_byte(self) -> Self {
         self
     }
 
     #[cfg(span_locations)]
-    fn last_byte(self) -> Self {
+    pub(crate) fn last_byte(self) -> Self {
         Span {
             lo: cmp::max(self.hi.saturating_sub(1), self.lo),
             hi: self.hi,
         }
     }
+
+    #[cfg(span_locations)]
+    fn is_call_site(&self) -> bool {
+        self.lo == 0 && self.hi == 0
+    }
 }
 
 impl Debug for Span {
@@ -594,7 +653,7 @@
 pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
     #[cfg(span_locations)]
     {
-        if span.lo == 0 && span.hi == 0 {
+        if span.is_call_site() {
             return;
         }
     }
diff --git a/src/lib.rs b/src/lib.rs
index 261c167..944bc8a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -86,7 +86,7 @@
 //! a different thread.
 
 // Proc-macro2 types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.51")]
+#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.54")]
 #![cfg_attr(
     any(proc_macro_span, super_unstable),
     feature(proc_macro_span, proc_macro_span_shrink)
@@ -98,6 +98,7 @@
     clippy::cast_possible_truncation,
     clippy::doc_markdown,
     clippy::items_after_statements,
+    clippy::let_underscore_untyped,
     clippy::manual_assert,
     clippy::must_use_candidate,
     clippy::needless_doctest_main,
@@ -133,6 +134,8 @@
 #[doc(hidden)]
 pub mod fallback;
 
+pub mod extra;
+
 #[cfg(not(wrap_proc_macro))]
 use crate::fallback as imp;
 #[path = "wrapper.rs"]
@@ -142,6 +145,7 @@
 #[cfg(span_locations)]
 mod location;
 
+use crate::extra::DelimSpan;
 use crate::marker::Marker;
 use core::cmp::Ordering;
 use core::fmt::{self, Debug, Display};
@@ -183,7 +187,7 @@
         }
     }
 
-    fn _new_stable(inner: fallback::TokenStream) -> Self {
+    fn _new_fallback(inner: fallback::TokenStream) -> Self {
         TokenStream {
             inner: inner.into(),
             _marker: Marker,
@@ -377,7 +381,7 @@
         }
     }
 
-    fn _new_stable(inner: fallback::Span) -> Self {
+    fn _new_fallback(inner: fallback::Span) -> Self {
         Span {
             inner: inner.into(),
             _marker: Marker,
@@ -524,6 +528,17 @@
     pub fn eq(&self, other: &Span) -> bool {
         self.inner.eq(&other.inner)
     }
+
+    /// Returns the source text behind a span. This preserves the original
+    /// source code, including spaces and comments. It only returns a result if
+    /// the span corresponds to real source code.
+    ///
+    /// Note: The observable result of a macro should only rely on the tokens
+    /// and not on this source text. The result of this function is a best
+    /// effort to be used for diagnostics only.
+    pub fn source_text(&self) -> Option<String> {
+        self.inner.source_text()
+    }
 }
 
 /// Prints a span in a form convenient for debugging.
@@ -664,7 +679,7 @@
         Group { inner }
     }
 
-    fn _new_stable(inner: fallback::Group) -> Self {
+    fn _new_fallback(inner: fallback::Group) -> Self {
         Group {
             inner: inner.into(),
         }
@@ -681,7 +696,8 @@
         }
     }
 
-    /// Returns the delimiter of this `Group`
+    /// Returns the punctuation used as the delimiter for this group: a set of
+    /// parentheses, square brackets, or curly braces.
     pub fn delimiter(&self) -> Delimiter {
         self.inner.delimiter()
     }
@@ -725,6 +741,13 @@
         Span::_new(self.inner.span_close())
     }
 
+    /// Returns an object that holds this group's `span_open()` and
+    /// `span_close()` together (in a more compact representation than holding
+    /// those 2 spans individually).
+    pub fn delim_span(&self) -> DelimSpan {
+        DelimSpan::new(&self.inner)
+    }
+
     /// Configures the span for this `Group`'s delimiters, but not its internal
     /// tokens.
     ///
@@ -1081,7 +1104,7 @@
         }
     }
 
-    fn _new_stable(inner: fallback::Literal) -> Self {
+    fn _new_fallback(inner: fallback::Literal) -> Self {
         Literal {
             inner: inner.into(),
             _marker: Marker,
diff --git a/src/parse.rs b/src/parse.rs
index 2a87948..82291da 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -217,13 +217,13 @@
                 hi: input.off,
             });
             trees = outer;
-            trees.push_token_from_parser(TokenTree::Group(crate::Group::_new_stable(g)));
+            trees.push_token_from_parser(TokenTree::Group(crate::Group::_new_fallback(g)));
         } else {
             let (rest, mut tt) = match leaf_token(input) {
                 Ok((rest, tt)) => (rest, tt),
                 Err(Reject) => return Err(lex_error(input)),
             };
-            tt.set_span(crate::Span::_new_stable(Span {
+            tt.set_span(crate::Span::_new_fallback(Span {
                 #[cfg(span_locations)]
                 lo,
                 #[cfg(span_locations)]
@@ -251,7 +251,7 @@
 fn leaf_token(input: Cursor) -> PResult<TokenTree> {
     if let Ok((input, l)) = literal(input) {
         // must be parsed before ident
-        Ok((input, TokenTree::Literal(crate::Literal::_new_stable(l))))
+        Ok((input, TokenTree::Literal(crate::Literal::_new_fallback(l))))
     } else if let Ok((input, p)) = punct(input) {
         Ok((input, TokenTree::Punct(p)))
     } else if let Ok((input, i)) = ident(input) {
@@ -795,7 +795,7 @@
     #[cfg(span_locations)]
     let lo = input.off;
     let (rest, (comment, inner)) = doc_comment_contents(input)?;
-    let span = crate::Span::_new_stable(Span {
+    let span = crate::Span::_new_fallback(Span {
         #[cfg(span_locations)]
         lo,
         #[cfg(span_locations)]
@@ -831,7 +831,7 @@
     bracketed.push_token_from_parser(TokenTree::Punct(equal));
     bracketed.push_token_from_parser(TokenTree::Literal(literal));
     let group = Group::new(Delimiter::Bracket, bracketed.build());
-    let mut group = crate::Group::_new_stable(group);
+    let mut group = crate::Group::_new_fallback(group);
     group.set_span(span);
     trees.push_token_from_parser(TokenTree::Group(group));
 
diff --git a/src/wrapper.rs b/src/wrapper.rs
index f5ec06b..00f67cd 100644
--- a/src/wrapper.rs
+++ b/src/wrapper.rs
@@ -40,7 +40,7 @@
 }
 
 fn mismatch() -> ! {
-    panic!("stable/nightly mismatch")
+    panic!("compiler/fallback mismatch")
 }
 
 impl DeferredTokenStream {
@@ -530,6 +530,16 @@
         }
     }
 
+    pub fn source_text(&self) -> Option<String> {
+        match self {
+            #[cfg(not(no_source_text))]
+            Span::Compiler(s) => s.source_text(),
+            #[cfg(no_source_text)]
+            Span::Compiler(_) => None,
+            Span::Fallback(s) => s.source_text(),
+        }
+    }
+
     fn unwrap_nightly(self) -> proc_macro::Span {
         match self {
             Span::Compiler(s) => s,
diff --git a/tests/marker.rs b/tests/marker.rs
index 4fb2beb..5b45733 100644
--- a/tests/marker.rs
+++ b/tests/marker.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::extra_unused_type_parameters)]
+
 use proc_macro2::{
     Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
 };
diff --git a/tests/test_size.rs b/tests/test_size.rs
new file mode 100644
index 0000000..46e58db
--- /dev/null
+++ b/tests/test_size.rs
@@ -0,0 +1,42 @@
+extern crate proc_macro;
+
+use std::mem;
+
+#[rustversion::attr(before(1.32), ignore)]
+#[test]
+fn test_proc_macro_span_size() {
+    assert_eq!(mem::size_of::<proc_macro::Span>(), 4);
+    assert_eq!(mem::size_of::<Option<proc_macro::Span>>(), 4);
+}
+
+#[cfg_attr(not(all(not(wrap_proc_macro), not(span_locations))), ignore)]
+#[test]
+fn test_proc_macro2_fallback_span_size_without_locations() {
+    assert_eq!(mem::size_of::<proc_macro2::Span>(), 0);
+    assert_eq!(mem::size_of::<Option<proc_macro2::Span>>(), 1);
+}
+
+#[cfg_attr(not(all(not(wrap_proc_macro), span_locations)), ignore)]
+#[test]
+fn test_proc_macro2_fallback_span_size_with_locations() {
+    assert_eq!(mem::size_of::<proc_macro2::Span>(), 8);
+    assert_eq!(mem::size_of::<Option<proc_macro2::Span>>(), 12);
+}
+
+#[rustversion::attr(before(1.32), ignore)]
+#[rustversion::attr(
+    since(1.32),
+    cfg_attr(not(all(wrap_proc_macro, not(span_locations))), ignore)
+)]
+#[test]
+fn test_proc_macro2_wrapper_span_size_without_locations() {
+    assert_eq!(mem::size_of::<proc_macro2::Span>(), 4);
+    assert_eq!(mem::size_of::<Option<proc_macro2::Span>>(), 8);
+}
+
+#[cfg_attr(not(all(wrap_proc_macro, span_locations)), ignore)]
+#[test]
+fn test_proc_macro2_wrapper_span_size_with_locations() {
+    assert_eq!(mem::size_of::<proc_macro2::Span>(), 12);
+    assert_eq!(mem::size_of::<Option<proc_macro2::Span>>(), 12);
+}