blob: e8e2e2ebe2440aac0f262ec0df79513210124554 [file] [log] [blame]
Alex Crichtonce0904d2018-08-27 17:29:49 -07001#![cfg_attr(not(super_unstable), allow(dead_code))]
Alex Crichtonaf5bad42018-03-27 14:45:10 -07002
Alex Crichtoncbec8ec2017-06-02 13:19:33 -07003use std::fmt;
4use std::iter;
David Tolnay78ef7732018-09-01 19:20:23 -07005use std::panic::{self, PanicInfo};
David Tolnay3d9d6ad2018-05-18 10:51:55 -07006use std::str::FromStr;
Alex Crichtoncbec8ec2017-06-02 13:19:33 -07007
8use proc_macro;
Alex Crichton30a4e9e2018-04-27 17:02:19 -07009use stable;
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070010
Alex Crichtonf3888432018-05-16 09:11:05 -070011use {Delimiter, Group, Punct, Spacing, TokenTree};
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070012
13#[derive(Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -070014pub enum TokenStream {
15 Nightly(proc_macro::TokenStream),
16 Stable(stable::TokenStream),
17}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070018
Alex Crichton30a4e9e2018-04-27 17:02:19 -070019pub enum LexError {
20 Nightly(proc_macro::LexError),
21 Stable(stable::LexError),
22}
23
24fn nightly_works() -> bool {
25 use std::sync::atomic::*;
David Tolnay2ed15d52018-09-01 08:46:12 -070026 use std::sync::Once;
27
Alex Crichton30a4e9e2018-04-27 17:02:19 -070028 static WORKS: AtomicUsize = ATOMIC_USIZE_INIT;
David Tolnay2ed15d52018-09-01 08:46:12 -070029 static INIT: Once = Once::new();
Alex Crichton30a4e9e2018-04-27 17:02:19 -070030
31 match WORKS.load(Ordering::SeqCst) {
32 1 => return false,
33 2 => return true,
34 _ => {}
35 }
David Tolnay2ed15d52018-09-01 08:46:12 -070036
37 // Swap in a null panic hook to avoid printing "thread panicked" to stderr,
38 // then use catch_unwind to determine whether the compiler's proc_macro is
39 // working. When proc-macro2 is used from outside of a procedural macro all
40 // of the proc_macro crate's APIs currently panic.
41 //
42 // The Once is to prevent the possibility of this ordering:
43 //
44 // thread 1 calls take_hook, gets the user's original hook
45 // thread 1 calls set_hook with the null hook
46 // thread 2 calls take_hook, thinks null hook is the original hook
47 // thread 2 calls set_hook with the null hook
48 // thread 1 calls set_hook with the actual original hook
49 // thread 2 calls set_hook with what it thinks is the original hook
50 //
51 // in which the user's hook has been lost.
52 //
53 // There is still a race condition where a panic in a different thread can
54 // happen during the interval that the user's original panic hook is
55 // unregistered such that their hook is incorrectly not called. This is
56 // sufficiently unlikely and less bad than printing panic messages to stderr
57 // on correct use of this crate. Maybe there is a libstd feature request
58 // here. For now, if a user needs to guarantee that this failure mode does
59 // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from
60 // the main thread before launching any other threads.
61 INIT.call_once(|| {
David Tolnay78ef7732018-09-01 19:20:23 -070062 type PanicHook = Fn(&PanicInfo) + Sync + Send + 'static;
63
64 let null_hook: Box<PanicHook> = Box::new(|_panic_info| { /* ignore */ });
65 let sanity_check = &*null_hook as *const PanicHook;
David Tolnay2ed15d52018-09-01 08:46:12 -070066 let original_hook = panic::take_hook();
David Tolnay78ef7732018-09-01 19:20:23 -070067 panic::set_hook(null_hook);
68
David Tolnay2ed15d52018-09-01 08:46:12 -070069 let works = panic::catch_unwind(|| proc_macro::Span::call_site()).is_ok();
70 WORKS.store(works as usize + 1, Ordering::SeqCst);
David Tolnay78ef7732018-09-01 19:20:23 -070071
72 let hopefully_null_hook = panic::take_hook();
David Tolnay2ed15d52018-09-01 08:46:12 -070073 panic::set_hook(original_hook);
David Tolnay78ef7732018-09-01 19:20:23 -070074 if sanity_check != &*hopefully_null_hook {
75 panic!("observed race condition in proc_macro2::nightly_works");
76 }
David Tolnay2ed15d52018-09-01 08:46:12 -070077 });
78 nightly_works()
Alex Crichton30a4e9e2018-04-27 17:02:19 -070079}
80
81fn mismatch() -> ! {
82 panic!("stable/nightly mismatch")
83}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070084
85impl TokenStream {
David Tolnayc3bb4592018-05-28 20:09:44 -070086 pub fn new() -> TokenStream {
Alex Crichton30a4e9e2018-04-27 17:02:19 -070087 if nightly_works() {
David Tolnayc3bb4592018-05-28 20:09:44 -070088 TokenStream::Nightly(proc_macro::TokenStream::new())
Alex Crichton30a4e9e2018-04-27 17:02:19 -070089 } else {
David Tolnayc3bb4592018-05-28 20:09:44 -070090 TokenStream::Stable(stable::TokenStream::new())
Alex Crichton30a4e9e2018-04-27 17:02:19 -070091 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -070092 }
93
94 pub fn is_empty(&self) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -070095 match self {
96 TokenStream::Nightly(tts) => tts.is_empty(),
97 TokenStream::Stable(tts) => tts.is_empty(),
98 }
99 }
100
101 fn unwrap_nightly(self) -> proc_macro::TokenStream {
102 match self {
103 TokenStream::Nightly(s) => s,
104 TokenStream::Stable(_) => mismatch(),
105 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700106 }
David Tolnay5c58c532018-08-13 11:33:51 -0700107
108 fn unwrap_stable(self) -> stable::TokenStream {
109 match self {
110 TokenStream::Nightly(_) => mismatch(),
111 TokenStream::Stable(s) => s,
112 }
113 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700114}
115
116impl FromStr for TokenStream {
117 type Err = LexError;
118
119 fn from_str(src: &str) -> Result<TokenStream, LexError> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700120 if nightly_works() {
121 Ok(TokenStream::Nightly(src.parse()?))
122 } else {
123 Ok(TokenStream::Stable(src.parse()?))
124 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700125 }
126}
127
128impl fmt::Display for TokenStream {
129 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700130 match self {
131 TokenStream::Nightly(tts) => tts.fmt(f),
132 TokenStream::Stable(tts) => tts.fmt(f),
133 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700134 }
135}
136
137impl From<proc_macro::TokenStream> for TokenStream {
138 fn from(inner: proc_macro::TokenStream) -> TokenStream {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700139 TokenStream::Nightly(inner)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700140 }
141}
142
143impl From<TokenStream> for proc_macro::TokenStream {
144 fn from(inner: TokenStream) -> proc_macro::TokenStream {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700145 match inner {
146 TokenStream::Nightly(inner) => inner,
147 TokenStream::Stable(inner) => inner.to_string().parse().unwrap(),
148 }
149 }
150}
151
152impl From<stable::TokenStream> for TokenStream {
153 fn from(inner: stable::TokenStream) -> TokenStream {
154 TokenStream::Stable(inner)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700155 }
156}
157
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700158impl From<TokenTree> for TokenStream {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700159 fn from(token: TokenTree) -> TokenStream {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700160 if !nightly_works() {
David Tolnay3d9d6ad2018-05-18 10:51:55 -0700161 return TokenStream::Stable(token.into());
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700162 }
Alex Crichton9cd80a62018-04-05 17:46:58 -0700163 let tt: proc_macro::TokenTree = match token {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700164 TokenTree::Group(tt) => {
165 let delim = match tt.delimiter() {
166 Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis,
167 Delimiter::Bracket => proc_macro::Delimiter::Bracket,
168 Delimiter::Brace => proc_macro::Delimiter::Brace,
169 Delimiter::None => proc_macro::Delimiter::None,
170 };
Alex Crichton9cd80a62018-04-05 17:46:58 -0700171 let span = tt.span();
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700172 let mut group = proc_macro::Group::new(delim, tt.stream.inner.unwrap_nightly());
173 group.set_span(span.inner.unwrap_nightly());
Alex Crichton9cd80a62018-04-05 17:46:58 -0700174 group.into()
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700175 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700176 TokenTree::Punct(tt) => {
Alex Crichton9cd80a62018-04-05 17:46:58 -0700177 let spacing = match tt.spacing() {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700178 Spacing::Joint => proc_macro::Spacing::Joint,
179 Spacing::Alone => proc_macro::Spacing::Alone,
180 };
Alex Crichtonf3888432018-05-16 09:11:05 -0700181 let mut op = proc_macro::Punct::new(tt.as_char(), spacing);
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700182 op.set_span(tt.span().inner.unwrap_nightly());
Alex Crichton9cd80a62018-04-05 17:46:58 -0700183 op.into()
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700184 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700185 TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700186 TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(),
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700187 };
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700188 TokenStream::Nightly(tt.into())
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700189 }
190}
191
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700192impl iter::FromIterator<TokenTree> for TokenStream {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700193 fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
194 if nightly_works() {
David Tolnay3d9d6ad2018-05-18 10:51:55 -0700195 let trees = trees
196 .into_iter()
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700197 .map(TokenStream::from)
David Tolnay3d9d6ad2018-05-18 10:51:55 -0700198 .flat_map(|t| match t {
199 TokenStream::Nightly(s) => s,
200 TokenStream::Stable(_) => mismatch(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700201 });
202 TokenStream::Nightly(trees.collect())
203 } else {
204 TokenStream::Stable(trees.into_iter().collect())
205 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700206 }
207}
208
Alex Crichton53b00672018-09-06 17:16:10 -0700209impl iter::FromIterator<TokenStream> for TokenStream {
210 fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
211 let mut streams = streams.into_iter();
212 match streams.next() {
213 #[cfg(slow_extend)]
214 Some(TokenStream::Nightly(first)) => {
215 let stream = iter::once(first).chain(streams.map(|s| {
216 match s {
217 TokenStream::Nightly(s) => s,
218 TokenStream::Stable(_) => mismatch(),
219 }
220 })).collect();
221 TokenStream::Nightly(stream)
222 }
223 #[cfg(not(slow_extend))]
224 Some(TokenStream::Nightly(mut first)) => {
225 first.extend(streams.map(|s| {
226 match s {
227 TokenStream::Nightly(s) => s,
228 TokenStream::Stable(_) => mismatch(),
229 }
230 }));
231 TokenStream::Nightly(first)
232 }
233 Some(TokenStream::Stable(mut first)) => {
234 first.extend(streams.map(|s| {
235 match s {
236 TokenStream::Stable(s) => s,
237 TokenStream::Nightly(_) => mismatch(),
238 }
239 }));
240 TokenStream::Stable(first)
241 }
242 None => TokenStream::new(),
243
244 }
245 }
246}
247
Alex Crichtonf3888432018-05-16 09:11:05 -0700248impl Extend<TokenTree> for TokenStream {
249 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
250 match self {
251 TokenStream::Nightly(tts) => {
David Tolnaye839e4f2018-09-06 09:36:43 -0700252 #[cfg(not(slow_extend))]
253 {
254 tts.extend(
255 streams
256 .into_iter()
257 .map(|t| TokenStream::from(t).unwrap_nightly()),
258 );
259 }
260 #[cfg(slow_extend)]
261 {
262 *tts = tts
263 .clone()
David Tolnay40d4ffd2018-08-12 13:49:09 -0700264 .into_iter()
David Tolnaye839e4f2018-09-06 09:36:43 -0700265 .chain(
266 streams
267 .into_iter()
268 .map(TokenStream::from)
269 .flat_map(|t| match t {
270 TokenStream::Nightly(tts) => tts.into_iter(),
271 _ => mismatch(),
272 }),
273 ).collect();
274 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700275 }
276 TokenStream::Stable(tts) => tts.extend(streams),
277 }
278 }
279}
280
David Tolnay5c58c532018-08-13 11:33:51 -0700281impl Extend<TokenStream> for TokenStream {
282 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
283 match self {
284 TokenStream::Nightly(tts) => {
David Tolnaye839e4f2018-09-06 09:36:43 -0700285 #[cfg(not(slow_extend))]
286 {
287 tts.extend(streams.into_iter().map(|stream| stream.unwrap_nightly()));
288 }
289 #[cfg(slow_extend)]
290 {
291 *tts = tts
292 .clone()
293 .into_iter()
294 .chain(
295 streams
296 .into_iter()
297 .flat_map(|t| match t {
298 TokenStream::Nightly(tts) => tts.into_iter(),
299 _ => mismatch(),
300 }),
301 ).collect();
302 }
David Tolnay5c58c532018-08-13 11:33:51 -0700303 }
304 TokenStream::Stable(tts) => {
305 tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable()))
306 }
307 }
308 }
309}
310
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700311impl fmt::Debug for TokenStream {
312 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700313 match self {
314 TokenStream::Nightly(tts) => tts.fmt(f),
315 TokenStream::Stable(tts) => tts.fmt(f),
316 }
317 }
318}
319
320impl From<proc_macro::LexError> for LexError {
321 fn from(e: proc_macro::LexError) -> LexError {
322 LexError::Nightly(e)
323 }
324}
325
326impl From<stable::LexError> for LexError {
327 fn from(e: stable::LexError) -> LexError {
328 LexError::Stable(e)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700329 }
330}
331
332impl fmt::Debug for LexError {
333 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700334 match self {
335 LexError::Nightly(e) => e.fmt(f),
336 LexError::Stable(e) => e.fmt(f),
337 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700338 }
339}
340
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700341pub enum TokenTreeIter {
342 Nightly(proc_macro::token_stream::IntoIter),
343 Stable(stable::TokenTreeIter),
344}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700345
346impl IntoIterator for TokenStream {
347 type Item = TokenTree;
Alex Crichton1a7f7622017-07-05 17:47:15 -0700348 type IntoIter = TokenTreeIter;
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700349
Alex Crichton1a7f7622017-07-05 17:47:15 -0700350 fn into_iter(self) -> TokenTreeIter {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700351 match self {
352 TokenStream::Nightly(tts) => TokenTreeIter::Nightly(tts.into_iter()),
353 TokenStream::Stable(tts) => TokenTreeIter::Stable(tts.into_iter()),
354 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700355 }
356}
357
Alex Crichton1a7f7622017-07-05 17:47:15 -0700358impl Iterator for TokenTreeIter {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700359 type Item = TokenTree;
360
361 fn next(&mut self) -> Option<TokenTree> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700362 let token = match self {
363 TokenTreeIter::Nightly(iter) => iter.next()?,
364 TokenTreeIter::Stable(iter) => return iter.next(),
365 };
Alex Crichton9cd80a62018-04-05 17:46:58 -0700366 Some(match token {
367 proc_macro::TokenTree::Group(tt) => {
368 let delim = match tt.delimiter() {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700369 proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
370 proc_macro::Delimiter::Bracket => Delimiter::Bracket,
371 proc_macro::Delimiter::Brace => Delimiter::Brace,
372 proc_macro::Delimiter::None => Delimiter::None,
373 };
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700374 let stream = ::TokenStream::_new(TokenStream::Nightly(tt.stream()));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700375 let mut g = Group::new(delim, stream);
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700376 g.set_span(::Span::_new(Span::Nightly(tt.span())));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700377 g.into()
378 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700379 proc_macro::TokenTree::Punct(tt) => {
Alex Crichton9cd80a62018-04-05 17:46:58 -0700380 let spacing = match tt.spacing() {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700381 proc_macro::Spacing::Joint => Spacing::Joint,
382 proc_macro::Spacing::Alone => Spacing::Alone,
383 };
Alex Crichtonf3888432018-05-16 09:11:05 -0700384 let mut o = Punct::new(tt.as_char(), spacing);
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700385 o.set_span(::Span::_new(Span::Nightly(tt.span())));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700386 o.into()
387 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700388 proc_macro::TokenTree::Ident(s) => ::Ident::_new(Ident::Nightly(s)).into(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700389 proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Nightly(l)).into(),
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700390 })
391 }
392
393 fn size_hint(&self) -> (usize, Option<usize>) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700394 match self {
395 TokenTreeIter::Nightly(tts) => tts.size_hint(),
396 TokenTreeIter::Stable(tts) => tts.size_hint(),
397 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700398 }
399}
400
Alex Crichton1a7f7622017-07-05 17:47:15 -0700401impl fmt::Debug for TokenTreeIter {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700402 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton1a7f7622017-07-05 17:47:15 -0700403 f.debug_struct("TokenTreeIter").finish()
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700404 }
405}
406
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700407pub use stable::FileName;
Nika Layzellb35a9a32017-12-30 14:34:35 -0500408
409// NOTE: We have to generate our own filename object here because we can't wrap
410// the one provided by proc_macro.
411#[derive(Clone, PartialEq, Eq)]
Alex Crichtonce0904d2018-08-27 17:29:49 -0700412#[cfg(super_unstable)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700413pub enum SourceFile {
414 Nightly(proc_macro::SourceFile, FileName),
415 Stable(stable::SourceFile),
416}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500417
Alex Crichtonce0904d2018-08-27 17:29:49 -0700418#[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500419impl SourceFile {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700420 fn nightly(sf: proc_macro::SourceFile) -> Self {
Alex Crichton9f0a28a2018-07-21 18:53:35 -0700421 let filename = stable::file_name(sf.path().display().to_string());
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700422 SourceFile::Nightly(sf, filename)
Nika Layzellb35a9a32017-12-30 14:34:35 -0500423 }
424
Nika Layzellf8d5f212017-12-11 14:07:02 -0500425 /// Get the path to this source file as a string.
Nika Layzellb35a9a32017-12-30 14:34:35 -0500426 pub fn path(&self) -> &FileName {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700427 match self {
428 SourceFile::Nightly(_, f) => f,
429 SourceFile::Stable(a) => a.path(),
430 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500431 }
432
433 pub fn is_real(&self) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700434 match self {
435 SourceFile::Nightly(a, _) => a.is_real(),
436 SourceFile::Stable(a) => a.is_real(),
437 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500438 }
439}
440
Alex Crichtonce0904d2018-08-27 17:29:49 -0700441#[cfg(super_unstable)]
Nika Layzellb35a9a32017-12-30 14:34:35 -0500442impl AsRef<FileName> for SourceFile {
443 fn as_ref(&self) -> &FileName {
444 self.path()
Nika Layzellf8d5f212017-12-11 14:07:02 -0500445 }
446}
447
Alex Crichtonce0904d2018-08-27 17:29:49 -0700448#[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500449impl fmt::Debug for SourceFile {
450 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700451 match self {
452 SourceFile::Nightly(a, _) => a.fmt(f),
453 SourceFile::Stable(a) => a.fmt(f),
454 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500455 }
456}
457
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500458pub struct LineColumn {
459 pub line: usize,
460 pub column: usize,
461}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500462
Alex Crichton9cd80a62018-04-05 17:46:58 -0700463#[derive(Copy, Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700464pub enum Span {
465 Nightly(proc_macro::Span),
466 Stable(stable::Span),
Sergio Benitez13805082018-01-04 01:25:45 -0800467}
468
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700469impl Span {
470 pub fn call_site() -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700471 if nightly_works() {
472 Span::Nightly(proc_macro::Span::call_site())
473 } else {
474 Span::Stable(stable::Span::call_site())
475 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700476 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700477
Alex Crichtonce0904d2018-08-27 17:29:49 -0700478 #[cfg(super_unstable)]
Alex Crichtone6085b72017-11-21 07:24:25 -0800479 pub fn def_site() -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700480 if nightly_works() {
481 Span::Nightly(proc_macro::Span::def_site())
482 } else {
483 Span::Stable(stable::Span::def_site())
484 }
Alex Crichton998f6422017-11-19 08:06:27 -0800485 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500486
Alex Crichtonce0904d2018-08-27 17:29:49 -0700487 #[cfg(super_unstable)]
David Tolnay4e8e3972018-01-05 18:10:22 -0800488 pub fn resolved_at(&self, other: Span) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700489 match (self, other) {
490 (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.resolved_at(b)),
491 (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.resolved_at(b)),
492 _ => mismatch(),
493 }
David Tolnay4e8e3972018-01-05 18:10:22 -0800494 }
495
Alex Crichtonce0904d2018-08-27 17:29:49 -0700496 #[cfg(super_unstable)]
David Tolnay4e8e3972018-01-05 18:10:22 -0800497 pub fn located_at(&self, other: Span) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700498 match (self, other) {
499 (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.located_at(b)),
500 (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.located_at(b)),
501 _ => mismatch(),
502 }
David Tolnay4e8e3972018-01-05 18:10:22 -0800503 }
504
David Tolnay16a17202017-12-31 10:47:24 -0500505 pub fn unstable(self) -> proc_macro::Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700506 match self {
507 Span::Nightly(s) => s,
508 Span::Stable(_) => mismatch(),
509 }
David Tolnay16a17202017-12-31 10:47:24 -0500510 }
511
Alex Crichtonce0904d2018-08-27 17:29:49 -0700512 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500513 pub fn source_file(&self) -> SourceFile {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700514 match self {
515 Span::Nightly(s) => SourceFile::nightly(s.source_file()),
516 Span::Stable(s) => SourceFile::Stable(s.source_file()),
517 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500518 }
519
Alex Crichtonce0904d2018-08-27 17:29:49 -0700520 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500521 pub fn start(&self) -> LineColumn {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700522 match self {
523 Span::Nightly(s) => {
524 let proc_macro::LineColumn { line, column } = s.start();
525 LineColumn { line, column }
526 }
527 Span::Stable(s) => {
528 let stable::LineColumn { line, column } = s.start();
529 LineColumn { line, column }
530 }
531 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500532 }
533
Alex Crichtonce0904d2018-08-27 17:29:49 -0700534 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500535 pub fn end(&self) -> LineColumn {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700536 match self {
537 Span::Nightly(s) => {
538 let proc_macro::LineColumn { line, column } = s.end();
539 LineColumn { line, column }
540 }
541 Span::Stable(s) => {
542 let stable::LineColumn { line, column } = s.end();
543 LineColumn { line, column }
544 }
545 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500546 }
547
Alex Crichtonce0904d2018-08-27 17:29:49 -0700548 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500549 pub fn join(&self, other: Span) -> Option<Span> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700550 let ret = match (self, other) {
551 (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.join(b)?),
552 (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.join(b)?),
553 _ => return None,
554 };
555 Some(ret)
Nika Layzellf8d5f212017-12-11 14:07:02 -0500556 }
Alex Crichtone24f7342018-04-05 17:58:11 -0700557
Alex Crichtonce0904d2018-08-27 17:29:49 -0700558 #[cfg(super_unstable)]
Alex Crichtone24f7342018-04-05 17:58:11 -0700559 pub fn eq(&self, other: &Span) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700560 match (self, other) {
561 (Span::Nightly(a), Span::Nightly(b)) => a.eq(b),
562 (Span::Stable(a), Span::Stable(b)) => a.eq(b),
563 _ => false,
564 }
565 }
566
567 fn unwrap_nightly(self) -> proc_macro::Span {
568 match self {
569 Span::Nightly(s) => s,
570 Span::Stable(_) => mismatch(),
571 }
572 }
573}
574
575impl From<proc_macro::Span> for ::Span {
576 fn from(proc_span: proc_macro::Span) -> ::Span {
577 ::Span::_new(Span::Nightly(proc_span))
578 }
579}
580
581impl From<stable::Span> for Span {
582 fn from(inner: stable::Span) -> Span {
583 Span::Stable(inner)
Alex Crichtone24f7342018-04-05 17:58:11 -0700584 }
Alex Crichton998f6422017-11-19 08:06:27 -0800585}
586
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700587impl fmt::Debug for Span {
588 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700589 match self {
590 Span::Nightly(s) => s.fmt(f),
591 Span::Stable(s) => s.fmt(f),
592 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700593 }
594}
595
Alex Crichtonf3888432018-05-16 09:11:05 -0700596#[derive(Clone)]
597pub enum Ident {
598 Nightly(proc_macro::Ident),
599 Stable(stable::Ident),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700600}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700601
Alex Crichtonf3888432018-05-16 09:11:05 -0700602impl Ident {
603 pub fn new(string: &str, span: Span) -> Ident {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700604 match span {
Alex Crichtonf3888432018-05-16 09:11:05 -0700605 Span::Nightly(s) => Ident::Nightly(proc_macro::Ident::new(string, s)),
606 Span::Stable(s) => Ident::Stable(stable::Ident::new(string, s)),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700607 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700608 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700609
Alex Crichtonf3888432018-05-16 09:11:05 -0700610 pub fn new_raw(string: &str, span: Span) -> Ident {
611 match span {
Alex Crichtonce0904d2018-08-27 17:29:49 -0700612 Span::Nightly(s) => {
613 let p: proc_macro::TokenStream = string.parse().unwrap();
614 let ident = match p.into_iter().next() {
615 Some(proc_macro::TokenTree::Ident(mut i)) => {
616 i.set_span(s);
617 i
618 }
619 _ => panic!(),
620 };
621 Ident::Nightly(ident)
622 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700623 Span::Stable(s) => Ident::Stable(stable::Ident::new_raw(string, s)),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700624 }
Alex Crichtonb2c94622018-04-04 07:36:41 -0700625 }
626
627 pub fn span(&self) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700628 match self {
Alex Crichtonf3888432018-05-16 09:11:05 -0700629 Ident::Nightly(t) => Span::Nightly(t.span()),
630 Ident::Stable(t) => Span::Stable(t.span()),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700631 }
Alex Crichtonb2c94622018-04-04 07:36:41 -0700632 }
633
634 pub fn set_span(&mut self, span: Span) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700635 match (self, span) {
Alex Crichtonf3888432018-05-16 09:11:05 -0700636 (Ident::Nightly(t), Span::Nightly(s)) => t.set_span(s),
637 (Ident::Stable(t), Span::Stable(s)) => t.set_span(s),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700638 _ => mismatch(),
639 }
640 }
641
Alex Crichtonf3888432018-05-16 09:11:05 -0700642 fn unwrap_nightly(self) -> proc_macro::Ident {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700643 match self {
Alex Crichtonf3888432018-05-16 09:11:05 -0700644 Ident::Nightly(s) => s,
645 Ident::Stable(_) => mismatch(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700646 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700647 }
648}
649
David Tolnayc0b0f2e2018-09-02 17:56:08 -0700650impl PartialEq for Ident {
651 fn eq(&self, other: &Ident) -> bool {
652 match (self, other) {
653 (Ident::Nightly(t), Ident::Nightly(o)) => t.to_string() == o.to_string(),
654 (Ident::Stable(t), Ident::Stable(o)) => t == o,
655 _ => mismatch(),
656 }
657 }
658}
659
660impl<T> PartialEq<T> for Ident
661where
662 T: ?Sized + AsRef<str>,
663{
664 fn eq(&self, other: &T) -> bool {
665 let other = other.as_ref();
666 match self {
667 Ident::Nightly(t) => t.to_string() == other,
668 Ident::Stable(t) => t == other,
669 }
670 }
671}
672
Alex Crichtonf3888432018-05-16 09:11:05 -0700673impl fmt::Display for Ident {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700674 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700675 match self {
Alex Crichtonf3888432018-05-16 09:11:05 -0700676 Ident::Nightly(t) => t.fmt(f),
677 Ident::Stable(t) => t.fmt(f),
678 }
679 }
680}
681
682impl fmt::Debug for Ident {
683 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
684 match self {
685 Ident::Nightly(t) => t.fmt(f),
686 Ident::Stable(t) => t.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700687 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700688 }
689}
690
691#[derive(Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700692pub enum Literal {
693 Nightly(proc_macro::Literal),
694 Stable(stable::Literal),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700695}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700696
Alex Crichtona914a612018-04-04 07:48:44 -0700697macro_rules! suffixed_numbers {
698 ($($name:ident => $kind:ident,)*) => ($(
699 pub fn $name(n: $kind) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700700 if nightly_works() {
701 Literal::Nightly(proc_macro::Literal::$name(n))
702 } else {
703 Literal::Stable(stable::Literal::$name(n))
704 }
Alex Crichtona914a612018-04-04 07:48:44 -0700705 }
706 )*)
707}
708
709macro_rules! unsuffixed_integers {
710 ($($name:ident => $kind:ident,)*) => ($(
711 pub fn $name(n: $kind) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700712 if nightly_works() {
713 Literal::Nightly(proc_macro::Literal::$name(n))
714 } else {
715 Literal::Stable(stable::Literal::$name(n))
716 }
Alex Crichtona914a612018-04-04 07:48:44 -0700717 }
718 )*)
719}
720
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700721impl Literal {
Alex Crichtona914a612018-04-04 07:48:44 -0700722 suffixed_numbers! {
723 u8_suffixed => u8,
724 u16_suffixed => u16,
725 u32_suffixed => u32,
726 u64_suffixed => u64,
727 usize_suffixed => usize,
728 i8_suffixed => i8,
729 i16_suffixed => i16,
730 i32_suffixed => i32,
731 i64_suffixed => i64,
732 isize_suffixed => isize,
733
734 f32_suffixed => f32,
735 f64_suffixed => f64,
736 }
737
738 unsuffixed_integers! {
739 u8_unsuffixed => u8,
740 u16_unsuffixed => u16,
741 u32_unsuffixed => u32,
742 u64_unsuffixed => u64,
743 usize_unsuffixed => usize,
744 i8_unsuffixed => i8,
745 i16_unsuffixed => i16,
746 i32_unsuffixed => i32,
747 i64_unsuffixed => i64,
748 isize_unsuffixed => isize,
749 }
750
751 pub fn f32_unsuffixed(f: f32) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700752 if nightly_works() {
753 Literal::Nightly(proc_macro::Literal::f32_unsuffixed(f))
754 } else {
755 Literal::Stable(stable::Literal::f32_unsuffixed(f))
756 }
Alex Crichtona914a612018-04-04 07:48:44 -0700757 }
758
759 pub fn f64_unsuffixed(f: f64) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700760 if nightly_works() {
761 Literal::Nightly(proc_macro::Literal::f64_unsuffixed(f))
762 } else {
763 Literal::Stable(stable::Literal::f64_unsuffixed(f))
764 }
Alex Crichtona914a612018-04-04 07:48:44 -0700765 }
766
Alex Crichtona914a612018-04-04 07:48:44 -0700767 pub fn string(t: &str) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700768 if nightly_works() {
769 Literal::Nightly(proc_macro::Literal::string(t))
770 } else {
771 Literal::Stable(stable::Literal::string(t))
772 }
Alex Crichtona914a612018-04-04 07:48:44 -0700773 }
774
775 pub fn character(t: char) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700776 if nightly_works() {
777 Literal::Nightly(proc_macro::Literal::character(t))
778 } else {
779 Literal::Stable(stable::Literal::character(t))
780 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700781 }
782
783 pub fn byte_string(bytes: &[u8]) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700784 if nightly_works() {
785 Literal::Nightly(proc_macro::Literal::byte_string(bytes))
786 } else {
787 Literal::Stable(stable::Literal::byte_string(bytes))
788 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700789 }
790
Alex Crichtonb2c94622018-04-04 07:36:41 -0700791 pub fn span(&self) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700792 match self {
793 Literal::Nightly(lit) => Span::Nightly(lit.span()),
794 Literal::Stable(lit) => Span::Stable(lit.span()),
795 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700796 }
797
Alex Crichtonb2c94622018-04-04 07:36:41 -0700798 pub fn set_span(&mut self, span: Span) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700799 match (self, span) {
800 (Literal::Nightly(lit), Span::Nightly(s)) => lit.set_span(s),
801 (Literal::Stable(lit), Span::Stable(s)) => lit.set_span(s),
802 _ => mismatch(),
803 }
804 }
805
806 fn unwrap_nightly(self) -> proc_macro::Literal {
807 match self {
808 Literal::Nightly(s) => s,
809 Literal::Stable(_) => mismatch(),
810 }
811 }
812}
813
814impl From<stable::Literal> for Literal {
815 fn from(s: stable::Literal) -> Literal {
816 Literal::Stable(s)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700817 }
818}
819
820impl fmt::Display for Literal {
821 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700822 match self {
823 Literal::Nightly(t) => t.fmt(f),
824 Literal::Stable(t) => t.fmt(f),
825 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700826 }
827}
828
829impl fmt::Debug for Literal {
830 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700831 match self {
832 Literal::Nightly(t) => t.fmt(f),
833 Literal::Stable(t) => t.fmt(f),
834 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700835 }
836}