blob: 69e8e8614134d1df061883ee522d91e1532d74a0 [file] [log] [blame]
Alex Crichtoncbec8ec2017-06-02 13:19:33 -07001use std::fmt;
2use std::iter;
David Tolnay78ef7732018-09-01 19:20:23 -07003use std::panic::{self, PanicInfo};
David Tolnay9cd3b4c2018-11-11 16:47:32 -08004#[cfg(super_unstable)]
5use std::path::PathBuf;
David Tolnay3d9d6ad2018-05-18 10:51:55 -07006use std::str::FromStr;
Alex Crichtoncbec8ec2017-06-02 13:19:33 -07007
David Tolnayaef075b2019-01-16 16:29:18 -08008use fallback;
David Tolnay471a7ed2019-01-19 21:00:11 -08009use proc_macro;
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070010
David Tolnayf14813f2018-09-08 17:14:07 -070011use {Delimiter, Punct, Spacing, TokenTree};
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070012
13#[derive(Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -070014pub enum TokenStream {
David Tolnay9204bac2019-01-19 19:26:17 -080015 Compiler(proc_macro::TokenStream),
16 Fallback(fallback::TokenStream),
Alex Crichton30a4e9e2018-04-27 17:02:19 -070017}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070018
Alex Crichton30a4e9e2018-04-27 17:02:19 -070019pub enum LexError {
David Tolnay9204bac2019-01-19 19:26:17 -080020 Compiler(proc_macro::LexError),
21 Fallback(fallback::LexError),
Alex Crichton30a4e9e2018-04-27 17:02:19 -070022}
23
24fn nightly_works() -> bool {
25 use std::sync::atomic::*;
David Tolnay2ed15d52018-09-01 08:46:12 -070026 use std::sync::Once;
27
David Tolnay35d24c32019-01-31 15:32:26 -080028 #[allow(deprecated)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -070029 static WORKS: AtomicUsize = ATOMIC_USIZE_INIT;
David Tolnay2ed15d52018-09-01 08:46:12 -070030 static INIT: Once = Once::new();
Alex Crichton30a4e9e2018-04-27 17:02:19 -070031
32 match WORKS.load(Ordering::SeqCst) {
33 1 => return false,
34 2 => return true,
35 _ => {}
36 }
David Tolnay2ed15d52018-09-01 08:46:12 -070037
38 // Swap in a null panic hook to avoid printing "thread panicked" to stderr,
39 // then use catch_unwind to determine whether the compiler's proc_macro is
40 // working. When proc-macro2 is used from outside of a procedural macro all
41 // of the proc_macro crate's APIs currently panic.
42 //
43 // The Once is to prevent the possibility of this ordering:
44 //
45 // thread 1 calls take_hook, gets the user's original hook
46 // thread 1 calls set_hook with the null hook
47 // thread 2 calls take_hook, thinks null hook is the original hook
48 // thread 2 calls set_hook with the null hook
49 // thread 1 calls set_hook with the actual original hook
50 // thread 2 calls set_hook with what it thinks is the original hook
51 //
52 // in which the user's hook has been lost.
53 //
54 // There is still a race condition where a panic in a different thread can
55 // happen during the interval that the user's original panic hook is
56 // unregistered such that their hook is incorrectly not called. This is
57 // sufficiently unlikely and less bad than printing panic messages to stderr
58 // on correct use of this crate. Maybe there is a libstd feature request
59 // here. For now, if a user needs to guarantee that this failure mode does
60 // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from
61 // the main thread before launching any other threads.
62 INIT.call_once(|| {
David Tolnayeac2b752019-07-19 11:55:12 -070063 type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static;
David Tolnay78ef7732018-09-01 19:20:23 -070064
65 let null_hook: Box<PanicHook> = Box::new(|_panic_info| { /* ignore */ });
66 let sanity_check = &*null_hook as *const PanicHook;
David Tolnay2ed15d52018-09-01 08:46:12 -070067 let original_hook = panic::take_hook();
David Tolnay78ef7732018-09-01 19:20:23 -070068 panic::set_hook(null_hook);
69
David Tolnay2ed15d52018-09-01 08:46:12 -070070 let works = panic::catch_unwind(|| proc_macro::Span::call_site()).is_ok();
71 WORKS.store(works as usize + 1, Ordering::SeqCst);
David Tolnay78ef7732018-09-01 19:20:23 -070072
73 let hopefully_null_hook = panic::take_hook();
David Tolnay2ed15d52018-09-01 08:46:12 -070074 panic::set_hook(original_hook);
David Tolnay78ef7732018-09-01 19:20:23 -070075 if sanity_check != &*hopefully_null_hook {
76 panic!("observed race condition in proc_macro2::nightly_works");
77 }
David Tolnay2ed15d52018-09-01 08:46:12 -070078 });
79 nightly_works()
Alex Crichton30a4e9e2018-04-27 17:02:19 -070080}
81
82fn mismatch() -> ! {
83 panic!("stable/nightly mismatch")
84}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070085
86impl TokenStream {
David Tolnayc3bb4592018-05-28 20:09:44 -070087 pub fn new() -> TokenStream {
Alex Crichton30a4e9e2018-04-27 17:02:19 -070088 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -080089 TokenStream::Compiler(proc_macro::TokenStream::new())
Alex Crichton30a4e9e2018-04-27 17:02:19 -070090 } else {
David Tolnay9204bac2019-01-19 19:26:17 -080091 TokenStream::Fallback(fallback::TokenStream::new())
Alex Crichton30a4e9e2018-04-27 17:02:19 -070092 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070093 }
94
95 pub fn is_empty(&self) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -070096 match self {
David Tolnay9204bac2019-01-19 19:26:17 -080097 TokenStream::Compiler(tts) => tts.is_empty(),
98 TokenStream::Fallback(tts) => tts.is_empty(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -070099 }
100 }
101
102 fn unwrap_nightly(self) -> proc_macro::TokenStream {
103 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800104 TokenStream::Compiler(s) => s,
105 TokenStream::Fallback(_) => mismatch(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700106 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700107 }
David Tolnay5c58c532018-08-13 11:33:51 -0700108
David Tolnayaef075b2019-01-16 16:29:18 -0800109 fn unwrap_stable(self) -> fallback::TokenStream {
David Tolnay5c58c532018-08-13 11:33:51 -0700110 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800111 TokenStream::Compiler(_) => mismatch(),
112 TokenStream::Fallback(s) => s,
David Tolnay5c58c532018-08-13 11:33:51 -0700113 }
114 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700115}
116
117impl FromStr for TokenStream {
118 type Err = LexError;
119
120 fn from_str(src: &str) -> Result<TokenStream, LexError> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700121 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800122 Ok(TokenStream::Compiler(src.parse()?))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700123 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800124 Ok(TokenStream::Fallback(src.parse()?))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700125 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700126 }
127}
128
129impl fmt::Display for TokenStream {
130 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700131 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800132 TokenStream::Compiler(tts) => tts.fmt(f),
133 TokenStream::Fallback(tts) => tts.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700134 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700135 }
136}
137
138impl From<proc_macro::TokenStream> for TokenStream {
139 fn from(inner: proc_macro::TokenStream) -> TokenStream {
David Tolnay9204bac2019-01-19 19:26:17 -0800140 TokenStream::Compiler(inner)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700141 }
142}
143
144impl From<TokenStream> for proc_macro::TokenStream {
145 fn from(inner: TokenStream) -> proc_macro::TokenStream {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700146 match inner {
David Tolnay9204bac2019-01-19 19:26:17 -0800147 TokenStream::Compiler(inner) => inner,
148 TokenStream::Fallback(inner) => inner.to_string().parse().unwrap(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700149 }
150 }
151}
152
David Tolnayaef075b2019-01-16 16:29:18 -0800153impl From<fallback::TokenStream> for TokenStream {
154 fn from(inner: fallback::TokenStream) -> TokenStream {
David Tolnay9204bac2019-01-19 19:26:17 -0800155 TokenStream::Fallback(inner)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700156 }
157}
158
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700159impl From<TokenTree> for TokenStream {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700160 fn from(token: TokenTree) -> TokenStream {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700161 if !nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800162 return TokenStream::Fallback(token.into());
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700163 }
Alex Crichton9cd80a62018-04-05 17:46:58 -0700164 let tt: proc_macro::TokenTree = match token {
David Tolnayf14813f2018-09-08 17:14:07 -0700165 TokenTree::Group(tt) => tt.inner.unwrap_nightly().into(),
Alex Crichtonf3888432018-05-16 09:11:05 -0700166 TokenTree::Punct(tt) => {
Alex Crichton9cd80a62018-04-05 17:46:58 -0700167 let spacing = match tt.spacing() {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700168 Spacing::Joint => proc_macro::Spacing::Joint,
169 Spacing::Alone => proc_macro::Spacing::Alone,
170 };
Alex Crichtonf3888432018-05-16 09:11:05 -0700171 let mut op = proc_macro::Punct::new(tt.as_char(), spacing);
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700172 op.set_span(tt.span().inner.unwrap_nightly());
Alex Crichton9cd80a62018-04-05 17:46:58 -0700173 op.into()
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700174 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700175 TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700176 TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(),
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700177 };
David Tolnay9204bac2019-01-19 19:26:17 -0800178 TokenStream::Compiler(tt.into())
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700179 }
180}
181
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700182impl iter::FromIterator<TokenTree> for TokenStream {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700183 fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
184 if nightly_works() {
David Tolnay3d9d6ad2018-05-18 10:51:55 -0700185 let trees = trees
186 .into_iter()
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700187 .map(TokenStream::from)
David Tolnay3d9d6ad2018-05-18 10:51:55 -0700188 .flat_map(|t| match t {
David Tolnay9204bac2019-01-19 19:26:17 -0800189 TokenStream::Compiler(s) => s,
190 TokenStream::Fallback(_) => mismatch(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700191 });
David Tolnay9204bac2019-01-19 19:26:17 -0800192 TokenStream::Compiler(trees.collect())
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700193 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800194 TokenStream::Fallback(trees.into_iter().collect())
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700195 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700196 }
197}
198
Alex Crichton53b00672018-09-06 17:16:10 -0700199impl iter::FromIterator<TokenStream> for TokenStream {
200 fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
201 let mut streams = streams.into_iter();
202 match streams.next() {
David Tolnay9204bac2019-01-19 19:26:17 -0800203 Some(TokenStream::Compiler(mut first)) => {
David Tolnay4453fcc2019-01-16 12:15:01 -0800204 first.extend(streams.map(|s| match s {
David Tolnay9204bac2019-01-19 19:26:17 -0800205 TokenStream::Compiler(s) => s,
206 TokenStream::Fallback(_) => mismatch(),
Alex Crichton53b00672018-09-06 17:16:10 -0700207 }));
David Tolnay9204bac2019-01-19 19:26:17 -0800208 TokenStream::Compiler(first)
Alex Crichton53b00672018-09-06 17:16:10 -0700209 }
David Tolnay9204bac2019-01-19 19:26:17 -0800210 Some(TokenStream::Fallback(mut first)) => {
David Tolnay4453fcc2019-01-16 12:15:01 -0800211 first.extend(streams.map(|s| match s {
David Tolnay9204bac2019-01-19 19:26:17 -0800212 TokenStream::Fallback(s) => s,
213 TokenStream::Compiler(_) => mismatch(),
Alex Crichton53b00672018-09-06 17:16:10 -0700214 }));
David Tolnay9204bac2019-01-19 19:26:17 -0800215 TokenStream::Fallback(first)
Alex Crichton53b00672018-09-06 17:16:10 -0700216 }
217 None => TokenStream::new(),
Alex Crichton53b00672018-09-06 17:16:10 -0700218 }
219 }
220}
221
Alex Crichtonf3888432018-05-16 09:11:05 -0700222impl Extend<TokenTree> for TokenStream {
223 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
224 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800225 TokenStream::Compiler(tts) => {
David Tolnay8418d422019-07-19 11:48:00 -0700226 tts.extend(
227 streams
228 .into_iter()
229 .map(|t| TokenStream::from(t).unwrap_nightly()),
230 );
Alex Crichtonf3888432018-05-16 09:11:05 -0700231 }
David Tolnay9204bac2019-01-19 19:26:17 -0800232 TokenStream::Fallback(tts) => tts.extend(streams),
Alex Crichtonf3888432018-05-16 09:11:05 -0700233 }
234 }
235}
236
David Tolnay5c58c532018-08-13 11:33:51 -0700237impl Extend<TokenStream> for TokenStream {
238 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
239 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800240 TokenStream::Compiler(tts) => {
David Tolnaye839e4f2018-09-06 09:36:43 -0700241 #[cfg(not(slow_extend))]
242 {
243 tts.extend(streams.into_iter().map(|stream| stream.unwrap_nightly()));
244 }
245 #[cfg(slow_extend)]
246 {
247 *tts = tts
248 .clone()
249 .into_iter()
David Tolnay4453fcc2019-01-16 12:15:01 -0800250 .chain(streams.into_iter().flat_map(|t| match t {
David Tolnay9204bac2019-01-19 19:26:17 -0800251 TokenStream::Compiler(tts) => tts.into_iter(),
David Tolnay4453fcc2019-01-16 12:15:01 -0800252 _ => mismatch(),
253 }))
254 .collect();
David Tolnaye839e4f2018-09-06 09:36:43 -0700255 }
David Tolnay5c58c532018-08-13 11:33:51 -0700256 }
David Tolnay9204bac2019-01-19 19:26:17 -0800257 TokenStream::Fallback(tts) => {
David Tolnay5c58c532018-08-13 11:33:51 -0700258 tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable()))
259 }
260 }
261 }
262}
263
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700264impl fmt::Debug for TokenStream {
265 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700266 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800267 TokenStream::Compiler(tts) => tts.fmt(f),
268 TokenStream::Fallback(tts) => tts.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700269 }
270 }
271}
272
273impl From<proc_macro::LexError> for LexError {
274 fn from(e: proc_macro::LexError) -> LexError {
David Tolnay9204bac2019-01-19 19:26:17 -0800275 LexError::Compiler(e)
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700276 }
277}
278
David Tolnayaef075b2019-01-16 16:29:18 -0800279impl From<fallback::LexError> for LexError {
280 fn from(e: fallback::LexError) -> LexError {
David Tolnay9204bac2019-01-19 19:26:17 -0800281 LexError::Fallback(e)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700282 }
283}
284
285impl fmt::Debug for LexError {
286 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700287 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800288 LexError::Compiler(e) => e.fmt(f),
289 LexError::Fallback(e) => e.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700290 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700291 }
292}
293
Isaac van Bakelf6754d32019-05-08 20:21:06 +0100294#[derive(Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700295pub enum TokenTreeIter {
David Tolnay9204bac2019-01-19 19:26:17 -0800296 Compiler(proc_macro::token_stream::IntoIter),
297 Fallback(fallback::TokenTreeIter),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700298}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700299
300impl IntoIterator for TokenStream {
301 type Item = TokenTree;
Alex Crichton1a7f7622017-07-05 17:47:15 -0700302 type IntoIter = TokenTreeIter;
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700303
Alex Crichton1a7f7622017-07-05 17:47:15 -0700304 fn into_iter(self) -> TokenTreeIter {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700305 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800306 TokenStream::Compiler(tts) => TokenTreeIter::Compiler(tts.into_iter()),
307 TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700308 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700309 }
310}
311
Alex Crichton1a7f7622017-07-05 17:47:15 -0700312impl Iterator for TokenTreeIter {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700313 type Item = TokenTree;
314
315 fn next(&mut self) -> Option<TokenTree> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700316 let token = match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800317 TokenTreeIter::Compiler(iter) => iter.next()?,
318 TokenTreeIter::Fallback(iter) => return iter.next(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700319 };
Alex Crichton9cd80a62018-04-05 17:46:58 -0700320 Some(match token {
David Tolnay9204bac2019-01-19 19:26:17 -0800321 proc_macro::TokenTree::Group(tt) => ::Group::_new(Group::Compiler(tt)).into(),
Alex Crichtonf3888432018-05-16 09:11:05 -0700322 proc_macro::TokenTree::Punct(tt) => {
Alex Crichton9cd80a62018-04-05 17:46:58 -0700323 let spacing = match tt.spacing() {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700324 proc_macro::Spacing::Joint => Spacing::Joint,
325 proc_macro::Spacing::Alone => Spacing::Alone,
326 };
Alex Crichtonf3888432018-05-16 09:11:05 -0700327 let mut o = Punct::new(tt.as_char(), spacing);
David Tolnay9204bac2019-01-19 19:26:17 -0800328 o.set_span(::Span::_new(Span::Compiler(tt.span())));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700329 o.into()
330 }
David Tolnay9204bac2019-01-19 19:26:17 -0800331 proc_macro::TokenTree::Ident(s) => ::Ident::_new(Ident::Compiler(s)).into(),
332 proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Compiler(l)).into(),
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700333 })
334 }
335
336 fn size_hint(&self) -> (usize, Option<usize>) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700337 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800338 TokenTreeIter::Compiler(tts) => tts.size_hint(),
339 TokenTreeIter::Fallback(tts) => tts.size_hint(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700340 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700341 }
342}
343
Alex Crichton1a7f7622017-07-05 17:47:15 -0700344impl fmt::Debug for TokenTreeIter {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700345 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton1a7f7622017-07-05 17:47:15 -0700346 f.debug_struct("TokenTreeIter").finish()
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700347 }
348}
349
Nika Layzellb35a9a32017-12-30 14:34:35 -0500350#[derive(Clone, PartialEq, Eq)]
Alex Crichtonce0904d2018-08-27 17:29:49 -0700351#[cfg(super_unstable)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700352pub enum SourceFile {
David Tolnay9204bac2019-01-19 19:26:17 -0800353 Compiler(proc_macro::SourceFile),
354 Fallback(fallback::SourceFile),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700355}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500356
Alex Crichtonce0904d2018-08-27 17:29:49 -0700357#[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500358impl SourceFile {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700359 fn nightly(sf: proc_macro::SourceFile) -> Self {
David Tolnay9204bac2019-01-19 19:26:17 -0800360 SourceFile::Compiler(sf)
Nika Layzellb35a9a32017-12-30 14:34:35 -0500361 }
362
Nika Layzellf8d5f212017-12-11 14:07:02 -0500363 /// Get the path to this source file as a string.
David Tolnay9cd3b4c2018-11-11 16:47:32 -0800364 pub fn path(&self) -> PathBuf {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700365 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800366 SourceFile::Compiler(a) => a.path(),
367 SourceFile::Fallback(a) => a.path(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700368 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500369 }
370
371 pub fn is_real(&self) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700372 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800373 SourceFile::Compiler(a) => a.is_real(),
374 SourceFile::Fallback(a) => a.is_real(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700375 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500376 }
377}
378
Alex Crichtonce0904d2018-08-27 17:29:49 -0700379#[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500380impl fmt::Debug for SourceFile {
381 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700382 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800383 SourceFile::Compiler(a) => a.fmt(f),
384 SourceFile::Fallback(a) => a.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700385 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500386 }
387}
388
David Tolnay3b1f7d22019-01-28 12:22:11 -0800389#[cfg(any(super_unstable, feature = "span-locations"))]
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500390pub struct LineColumn {
391 pub line: usize,
392 pub column: usize,
393}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500394
Alex Crichton9cd80a62018-04-05 17:46:58 -0700395#[derive(Copy, Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700396pub enum Span {
David Tolnay9204bac2019-01-19 19:26:17 -0800397 Compiler(proc_macro::Span),
398 Fallback(fallback::Span),
Sergio Benitez13805082018-01-04 01:25:45 -0800399}
400
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700401impl Span {
402 pub fn call_site() -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700403 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800404 Span::Compiler(proc_macro::Span::call_site())
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700405 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800406 Span::Fallback(fallback::Span::call_site())
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700407 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700408 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700409
Alex Crichtonce0904d2018-08-27 17:29:49 -0700410 #[cfg(super_unstable)]
Alex Crichtone6085b72017-11-21 07:24:25 -0800411 pub fn def_site() -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700412 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800413 Span::Compiler(proc_macro::Span::def_site())
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700414 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800415 Span::Fallback(fallback::Span::def_site())
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700416 }
Alex Crichton998f6422017-11-19 08:06:27 -0800417 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500418
Alex Crichtonce0904d2018-08-27 17:29:49 -0700419 #[cfg(super_unstable)]
David Tolnay4e8e3972018-01-05 18:10:22 -0800420 pub fn resolved_at(&self, other: Span) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700421 match (self, other) {
David Tolnay9204bac2019-01-19 19:26:17 -0800422 (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)),
423 (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700424 _ => mismatch(),
425 }
David Tolnay4e8e3972018-01-05 18:10:22 -0800426 }
427
Alex Crichtonce0904d2018-08-27 17:29:49 -0700428 #[cfg(super_unstable)]
David Tolnay4e8e3972018-01-05 18:10:22 -0800429 pub fn located_at(&self, other: Span) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700430 match (self, other) {
David Tolnay9204bac2019-01-19 19:26:17 -0800431 (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)),
432 (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700433 _ => mismatch(),
434 }
David Tolnay4e8e3972018-01-05 18:10:22 -0800435 }
436
David Tolnay40bbb1c2019-01-19 19:43:55 -0800437 pub fn unwrap(self) -> proc_macro::Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700438 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800439 Span::Compiler(s) => s,
440 Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700441 }
David Tolnay16a17202017-12-31 10:47:24 -0500442 }
443
Alex Crichtonce0904d2018-08-27 17:29:49 -0700444 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500445 pub fn source_file(&self) -> SourceFile {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700446 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800447 Span::Compiler(s) => SourceFile::nightly(s.source_file()),
448 Span::Fallback(s) => SourceFile::Fallback(s.source_file()),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700449 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500450 }
451
David Tolnay3b1f7d22019-01-28 12:22:11 -0800452 #[cfg(any(super_unstable, feature = "span-locations"))]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500453 pub fn start(&self) -> LineColumn {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700454 match self {
David Tolnayb455dd72019-04-28 13:50:51 -0700455 #[cfg(proc_macro_span)]
David Tolnay9204bac2019-01-19 19:26:17 -0800456 Span::Compiler(s) => {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700457 let proc_macro::LineColumn { line, column } = s.start();
458 LineColumn { line, column }
459 }
David Tolnayb455dd72019-04-28 13:50:51 -0700460 #[cfg(not(proc_macro_span))]
David Tolnay3b1f7d22019-01-28 12:22:11 -0800461 Span::Compiler(_) => LineColumn { line: 0, column: 0 },
David Tolnay9204bac2019-01-19 19:26:17 -0800462 Span::Fallback(s) => {
David Tolnayaef075b2019-01-16 16:29:18 -0800463 let fallback::LineColumn { line, column } = s.start();
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700464 LineColumn { line, column }
465 }
466 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500467 }
468
David Tolnay3b1f7d22019-01-28 12:22:11 -0800469 #[cfg(any(super_unstable, feature = "span-locations"))]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500470 pub fn end(&self) -> LineColumn {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700471 match self {
David Tolnayb455dd72019-04-28 13:50:51 -0700472 #[cfg(proc_macro_span)]
David Tolnay9204bac2019-01-19 19:26:17 -0800473 Span::Compiler(s) => {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700474 let proc_macro::LineColumn { line, column } = s.end();
475 LineColumn { line, column }
476 }
David Tolnayb455dd72019-04-28 13:50:51 -0700477 #[cfg(not(proc_macro_span))]
David Tolnay3b1f7d22019-01-28 12:22:11 -0800478 Span::Compiler(_) => LineColumn { line: 0, column: 0 },
David Tolnay9204bac2019-01-19 19:26:17 -0800479 Span::Fallback(s) => {
David Tolnayaef075b2019-01-16 16:29:18 -0800480 let fallback::LineColumn { line, column } = s.end();
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700481 LineColumn { line, column }
482 }
483 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500484 }
485
Alex Crichtonce0904d2018-08-27 17:29:49 -0700486 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500487 pub fn join(&self, other: Span) -> Option<Span> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700488 let ret = match (self, other) {
David Tolnay9204bac2019-01-19 19:26:17 -0800489 (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?),
490 (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700491 _ => return None,
492 };
493 Some(ret)
Nika Layzellf8d5f212017-12-11 14:07:02 -0500494 }
Alex Crichtone24f7342018-04-05 17:58:11 -0700495
Alex Crichtonce0904d2018-08-27 17:29:49 -0700496 #[cfg(super_unstable)]
Alex Crichtone24f7342018-04-05 17:58:11 -0700497 pub fn eq(&self, other: &Span) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700498 match (self, other) {
David Tolnay9204bac2019-01-19 19:26:17 -0800499 (Span::Compiler(a), Span::Compiler(b)) => a.eq(b),
500 (Span::Fallback(a), Span::Fallback(b)) => a.eq(b),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700501 _ => false,
502 }
503 }
504
505 fn unwrap_nightly(self) -> proc_macro::Span {
506 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800507 Span::Compiler(s) => s,
508 Span::Fallback(_) => mismatch(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700509 }
510 }
511}
512
513impl From<proc_macro::Span> for ::Span {
514 fn from(proc_span: proc_macro::Span) -> ::Span {
David Tolnay9204bac2019-01-19 19:26:17 -0800515 ::Span::_new(Span::Compiler(proc_span))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700516 }
517}
518
David Tolnayaef075b2019-01-16 16:29:18 -0800519impl From<fallback::Span> for Span {
520 fn from(inner: fallback::Span) -> Span {
David Tolnay9204bac2019-01-19 19:26:17 -0800521 Span::Fallback(inner)
Alex Crichtone24f7342018-04-05 17:58:11 -0700522 }
Alex Crichton998f6422017-11-19 08:06:27 -0800523}
524
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700525impl fmt::Debug for Span {
526 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700527 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800528 Span::Compiler(s) => s.fmt(f),
529 Span::Fallback(s) => s.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700530 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700531 }
532}
533
David Tolnayfd8cdc82019-01-19 19:23:59 -0800534pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
535 match span {
536 Span::Compiler(s) => {
537 debug.field("span", &s);
538 }
539 Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s),
540 }
541}
542
Alex Crichtonf3888432018-05-16 09:11:05 -0700543#[derive(Clone)]
David Tolnayf14813f2018-09-08 17:14:07 -0700544pub enum Group {
David Tolnay9204bac2019-01-19 19:26:17 -0800545 Compiler(proc_macro::Group),
546 Fallback(fallback::Group),
David Tolnayf14813f2018-09-08 17:14:07 -0700547}
548
549impl Group {
550 pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
551 match stream {
David Tolnay9204bac2019-01-19 19:26:17 -0800552 TokenStream::Compiler(stream) => {
David Tolnayf14813f2018-09-08 17:14:07 -0700553 let delimiter = match delimiter {
554 Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis,
555 Delimiter::Bracket => proc_macro::Delimiter::Bracket,
556 Delimiter::Brace => proc_macro::Delimiter::Brace,
557 Delimiter::None => proc_macro::Delimiter::None,
558 };
David Tolnay9204bac2019-01-19 19:26:17 -0800559 Group::Compiler(proc_macro::Group::new(delimiter, stream))
David Tolnayf14813f2018-09-08 17:14:07 -0700560 }
David Tolnay471a7ed2019-01-19 21:00:11 -0800561 TokenStream::Fallback(stream) => {
562 Group::Fallback(fallback::Group::new(delimiter, stream))
563 }
David Tolnayf14813f2018-09-08 17:14:07 -0700564 }
565 }
566
567 pub fn delimiter(&self) -> Delimiter {
568 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800569 Group::Compiler(g) => match g.delimiter() {
David Tolnayf14813f2018-09-08 17:14:07 -0700570 proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
571 proc_macro::Delimiter::Bracket => Delimiter::Bracket,
572 proc_macro::Delimiter::Brace => Delimiter::Brace,
573 proc_macro::Delimiter::None => Delimiter::None,
David Tolnay4453fcc2019-01-16 12:15:01 -0800574 },
David Tolnay9204bac2019-01-19 19:26:17 -0800575 Group::Fallback(g) => g.delimiter(),
David Tolnayf14813f2018-09-08 17:14:07 -0700576 }
577 }
578
579 pub fn stream(&self) -> TokenStream {
580 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800581 Group::Compiler(g) => TokenStream::Compiler(g.stream()),
582 Group::Fallback(g) => TokenStream::Fallback(g.stream()),
David Tolnayf14813f2018-09-08 17:14:07 -0700583 }
584 }
585
586 pub fn span(&self) -> Span {
587 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800588 Group::Compiler(g) => Span::Compiler(g.span()),
589 Group::Fallback(g) => Span::Fallback(g.span()),
David Tolnayf14813f2018-09-08 17:14:07 -0700590 }
591 }
592
593 #[cfg(super_unstable)]
594 pub fn span_open(&self) -> Span {
595 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800596 Group::Compiler(g) => Span::Compiler(g.span_open()),
597 Group::Fallback(g) => Span::Fallback(g.span_open()),
David Tolnayf14813f2018-09-08 17:14:07 -0700598 }
599 }
600
601 #[cfg(super_unstable)]
602 pub fn span_close(&self) -> Span {
603 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800604 Group::Compiler(g) => Span::Compiler(g.span_close()),
605 Group::Fallback(g) => Span::Fallback(g.span_close()),
David Tolnayf14813f2018-09-08 17:14:07 -0700606 }
607 }
608
609 pub fn set_span(&mut self, span: Span) {
610 match (self, span) {
David Tolnay9204bac2019-01-19 19:26:17 -0800611 (Group::Compiler(g), Span::Compiler(s)) => g.set_span(s),
612 (Group::Fallback(g), Span::Fallback(s)) => g.set_span(s),
David Tolnayf14813f2018-09-08 17:14:07 -0700613 _ => mismatch(),
614 }
615 }
616
617 fn unwrap_nightly(self) -> proc_macro::Group {
618 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800619 Group::Compiler(g) => g,
620 Group::Fallback(_) => mismatch(),
David Tolnayf14813f2018-09-08 17:14:07 -0700621 }
622 }
623}
624
David Tolnayaef075b2019-01-16 16:29:18 -0800625impl From<fallback::Group> for Group {
626 fn from(g: fallback::Group) -> Self {
David Tolnay9204bac2019-01-19 19:26:17 -0800627 Group::Fallback(g)
David Tolnayf14813f2018-09-08 17:14:07 -0700628 }
629}
630
631impl fmt::Display for Group {
632 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
633 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800634 Group::Compiler(group) => group.fmt(formatter),
635 Group::Fallback(group) => group.fmt(formatter),
David Tolnayf14813f2018-09-08 17:14:07 -0700636 }
637 }
638}
639
640impl fmt::Debug for Group {
641 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
642 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800643 Group::Compiler(group) => group.fmt(formatter),
644 Group::Fallback(group) => group.fmt(formatter),
David Tolnayf14813f2018-09-08 17:14:07 -0700645 }
646 }
647}
648
649#[derive(Clone)]
Alex Crichtonf3888432018-05-16 09:11:05 -0700650pub enum Ident {
David Tolnay9204bac2019-01-19 19:26:17 -0800651 Compiler(proc_macro::Ident),
652 Fallback(fallback::Ident),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700653}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700654
Alex Crichtonf3888432018-05-16 09:11:05 -0700655impl Ident {
656 pub fn new(string: &str, span: Span) -> Ident {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700657 match span {
David Tolnay9204bac2019-01-19 19:26:17 -0800658 Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)),
659 Span::Fallback(s) => Ident::Fallback(fallback::Ident::new(string, s)),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700660 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700661 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700662
Alex Crichtonf3888432018-05-16 09:11:05 -0700663 pub fn new_raw(string: &str, span: Span) -> Ident {
664 match span {
David Tolnay9204bac2019-01-19 19:26:17 -0800665 Span::Compiler(s) => {
Alex Crichtonce0904d2018-08-27 17:29:49 -0700666 let p: proc_macro::TokenStream = string.parse().unwrap();
667 let ident = match p.into_iter().next() {
668 Some(proc_macro::TokenTree::Ident(mut i)) => {
669 i.set_span(s);
670 i
671 }
672 _ => panic!(),
673 };
David Tolnay9204bac2019-01-19 19:26:17 -0800674 Ident::Compiler(ident)
Alex Crichtonce0904d2018-08-27 17:29:49 -0700675 }
David Tolnay9204bac2019-01-19 19:26:17 -0800676 Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw(string, s)),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700677 }
Alex Crichtonb2c94622018-04-04 07:36:41 -0700678 }
679
680 pub fn span(&self) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700681 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800682 Ident::Compiler(t) => Span::Compiler(t.span()),
683 Ident::Fallback(t) => Span::Fallback(t.span()),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700684 }
Alex Crichtonb2c94622018-04-04 07:36:41 -0700685 }
686
687 pub fn set_span(&mut self, span: Span) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700688 match (self, span) {
David Tolnay9204bac2019-01-19 19:26:17 -0800689 (Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s),
690 (Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700691 _ => mismatch(),
692 }
693 }
694
Alex Crichtonf3888432018-05-16 09:11:05 -0700695 fn unwrap_nightly(self) -> proc_macro::Ident {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700696 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800697 Ident::Compiler(s) => s,
698 Ident::Fallback(_) => mismatch(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700699 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700700 }
701}
702
David Tolnayc0b0f2e2018-09-02 17:56:08 -0700703impl PartialEq for Ident {
704 fn eq(&self, other: &Ident) -> bool {
705 match (self, other) {
David Tolnay9204bac2019-01-19 19:26:17 -0800706 (Ident::Compiler(t), Ident::Compiler(o)) => t.to_string() == o.to_string(),
707 (Ident::Fallback(t), Ident::Fallback(o)) => t == o,
David Tolnayc0b0f2e2018-09-02 17:56:08 -0700708 _ => mismatch(),
709 }
710 }
711}
712
713impl<T> PartialEq<T> for Ident
714where
715 T: ?Sized + AsRef<str>,
716{
717 fn eq(&self, other: &T) -> bool {
718 let other = other.as_ref();
719 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800720 Ident::Compiler(t) => t.to_string() == other,
721 Ident::Fallback(t) => t == other,
David Tolnayc0b0f2e2018-09-02 17:56:08 -0700722 }
723 }
724}
725
Alex Crichtonf3888432018-05-16 09:11:05 -0700726impl fmt::Display for Ident {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700727 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700728 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800729 Ident::Compiler(t) => t.fmt(f),
730 Ident::Fallback(t) => t.fmt(f),
Alex Crichtonf3888432018-05-16 09:11:05 -0700731 }
732 }
733}
734
735impl fmt::Debug for Ident {
736 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
737 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800738 Ident::Compiler(t) => t.fmt(f),
739 Ident::Fallback(t) => t.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700740 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700741 }
742}
743
744#[derive(Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700745pub enum Literal {
David Tolnay9204bac2019-01-19 19:26:17 -0800746 Compiler(proc_macro::Literal),
747 Fallback(fallback::Literal),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700748}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700749
Alex Crichtona914a612018-04-04 07:48:44 -0700750macro_rules! suffixed_numbers {
751 ($($name:ident => $kind:ident,)*) => ($(
752 pub fn $name(n: $kind) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700753 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800754 Literal::Compiler(proc_macro::Literal::$name(n))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700755 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800756 Literal::Fallback(fallback::Literal::$name(n))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700757 }
Alex Crichtona914a612018-04-04 07:48:44 -0700758 }
759 )*)
760}
761
762macro_rules! unsuffixed_integers {
763 ($($name:ident => $kind:ident,)*) => ($(
764 pub fn $name(n: $kind) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700765 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800766 Literal::Compiler(proc_macro::Literal::$name(n))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700767 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800768 Literal::Fallback(fallback::Literal::$name(n))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700769 }
Alex Crichtona914a612018-04-04 07:48:44 -0700770 }
771 )*)
772}
773
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700774impl Literal {
Alex Crichtona914a612018-04-04 07:48:44 -0700775 suffixed_numbers! {
776 u8_suffixed => u8,
777 u16_suffixed => u16,
778 u32_suffixed => u32,
779 u64_suffixed => u64,
David Tolnay1596a8c2019-07-19 11:45:26 -0700780 u128_suffixed => u128,
Alex Crichtona914a612018-04-04 07:48:44 -0700781 usize_suffixed => usize,
782 i8_suffixed => i8,
783 i16_suffixed => i16,
784 i32_suffixed => i32,
785 i64_suffixed => i64,
David Tolnay1596a8c2019-07-19 11:45:26 -0700786 i128_suffixed => i128,
Alex Crichtona914a612018-04-04 07:48:44 -0700787 isize_suffixed => isize,
788
789 f32_suffixed => f32,
790 f64_suffixed => f64,
791 }
792
793 unsuffixed_integers! {
794 u8_unsuffixed => u8,
795 u16_unsuffixed => u16,
796 u32_unsuffixed => u32,
797 u64_unsuffixed => u64,
David Tolnay1596a8c2019-07-19 11:45:26 -0700798 u128_unsuffixed => u128,
Alex Crichtona914a612018-04-04 07:48:44 -0700799 usize_unsuffixed => usize,
800 i8_unsuffixed => i8,
801 i16_unsuffixed => i16,
802 i32_unsuffixed => i32,
803 i64_unsuffixed => i64,
Alex Crichton69385662018-11-08 06:30:04 -0800804 i128_unsuffixed => i128,
David Tolnay1596a8c2019-07-19 11:45:26 -0700805 isize_unsuffixed => isize,
Alex Crichton69385662018-11-08 06:30:04 -0800806 }
807
Alex Crichtona914a612018-04-04 07:48:44 -0700808 pub fn f32_unsuffixed(f: f32) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700809 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800810 Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700811 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800812 Literal::Fallback(fallback::Literal::f32_unsuffixed(f))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700813 }
Alex Crichtona914a612018-04-04 07:48:44 -0700814 }
815
816 pub fn f64_unsuffixed(f: f64) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700817 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800818 Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700819 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800820 Literal::Fallback(fallback::Literal::f64_unsuffixed(f))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700821 }
Alex Crichtona914a612018-04-04 07:48:44 -0700822 }
823
Alex Crichtona914a612018-04-04 07:48:44 -0700824 pub fn string(t: &str) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700825 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800826 Literal::Compiler(proc_macro::Literal::string(t))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700827 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800828 Literal::Fallback(fallback::Literal::string(t))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700829 }
Alex Crichtona914a612018-04-04 07:48:44 -0700830 }
831
832 pub fn character(t: char) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700833 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800834 Literal::Compiler(proc_macro::Literal::character(t))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700835 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800836 Literal::Fallback(fallback::Literal::character(t))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700837 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700838 }
839
840 pub fn byte_string(bytes: &[u8]) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700841 if nightly_works() {
David Tolnay9204bac2019-01-19 19:26:17 -0800842 Literal::Compiler(proc_macro::Literal::byte_string(bytes))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700843 } else {
David Tolnay9204bac2019-01-19 19:26:17 -0800844 Literal::Fallback(fallback::Literal::byte_string(bytes))
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700845 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700846 }
847
Alex Crichtonb2c94622018-04-04 07:36:41 -0700848 pub fn span(&self) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700849 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800850 Literal::Compiler(lit) => Span::Compiler(lit.span()),
851 Literal::Fallback(lit) => Span::Fallback(lit.span()),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700852 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700853 }
854
Alex Crichtonb2c94622018-04-04 07:36:41 -0700855 pub fn set_span(&mut self, span: Span) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700856 match (self, span) {
David Tolnay9204bac2019-01-19 19:26:17 -0800857 (Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s),
858 (Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700859 _ => mismatch(),
860 }
861 }
862
863 fn unwrap_nightly(self) -> proc_macro::Literal {
864 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800865 Literal::Compiler(s) => s,
866 Literal::Fallback(_) => mismatch(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700867 }
868 }
869}
870
David Tolnayaef075b2019-01-16 16:29:18 -0800871impl From<fallback::Literal> for Literal {
872 fn from(s: fallback::Literal) -> Literal {
David Tolnay9204bac2019-01-19 19:26:17 -0800873 Literal::Fallback(s)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700874 }
875}
876
877impl fmt::Display for Literal {
878 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700879 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800880 Literal::Compiler(t) => t.fmt(f),
881 Literal::Fallback(t) => t.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700882 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700883 }
884}
885
886impl fmt::Debug for Literal {
887 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700888 match self {
David Tolnay9204bac2019-01-19 19:26:17 -0800889 Literal::Compiler(t) => t.fmt(f),
890 Literal::Fallback(t) => t.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700891 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700892 }
893}