blob: 3e940ca72ac9a6d88f67a103db9c1f913a6b8454 [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 Crichtonf3888432018-05-16 09:11:05 -0700209impl Extend<TokenTree> for TokenStream {
210 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
211 match self {
212 TokenStream::Nightly(tts) => {
David Tolnaye839e4f2018-09-06 09:36:43 -0700213 #[cfg(not(slow_extend))]
214 {
215 tts.extend(
216 streams
217 .into_iter()
218 .map(|t| TokenStream::from(t).unwrap_nightly()),
219 );
220 }
221 #[cfg(slow_extend)]
222 {
223 *tts = tts
224 .clone()
David Tolnay40d4ffd2018-08-12 13:49:09 -0700225 .into_iter()
David Tolnaye839e4f2018-09-06 09:36:43 -0700226 .chain(
227 streams
228 .into_iter()
229 .map(TokenStream::from)
230 .flat_map(|t| match t {
231 TokenStream::Nightly(tts) => tts.into_iter(),
232 _ => mismatch(),
233 }),
234 ).collect();
235 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700236 }
237 TokenStream::Stable(tts) => tts.extend(streams),
238 }
239 }
240}
241
David Tolnay5c58c532018-08-13 11:33:51 -0700242impl Extend<TokenStream> for TokenStream {
243 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
244 match self {
245 TokenStream::Nightly(tts) => {
David Tolnaye839e4f2018-09-06 09:36:43 -0700246 #[cfg(not(slow_extend))]
247 {
248 tts.extend(streams.into_iter().map(|stream| stream.unwrap_nightly()));
249 }
250 #[cfg(slow_extend)]
251 {
252 *tts = tts
253 .clone()
254 .into_iter()
255 .chain(
256 streams
257 .into_iter()
258 .flat_map(|t| match t {
259 TokenStream::Nightly(tts) => tts.into_iter(),
260 _ => mismatch(),
261 }),
262 ).collect();
263 }
David Tolnay5c58c532018-08-13 11:33:51 -0700264 }
265 TokenStream::Stable(tts) => {
266 tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable()))
267 }
268 }
269 }
270}
271
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700272impl fmt::Debug for TokenStream {
273 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700274 match self {
275 TokenStream::Nightly(tts) => tts.fmt(f),
276 TokenStream::Stable(tts) => tts.fmt(f),
277 }
278 }
279}
280
281impl From<proc_macro::LexError> for LexError {
282 fn from(e: proc_macro::LexError) -> LexError {
283 LexError::Nightly(e)
284 }
285}
286
287impl From<stable::LexError> for LexError {
288 fn from(e: stable::LexError) -> LexError {
289 LexError::Stable(e)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700290 }
291}
292
293impl fmt::Debug for LexError {
294 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700295 match self {
296 LexError::Nightly(e) => e.fmt(f),
297 LexError::Stable(e) => e.fmt(f),
298 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700299 }
300}
301
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700302pub enum TokenTreeIter {
303 Nightly(proc_macro::token_stream::IntoIter),
304 Stable(stable::TokenTreeIter),
305}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700306
307impl IntoIterator for TokenStream {
308 type Item = TokenTree;
Alex Crichton1a7f7622017-07-05 17:47:15 -0700309 type IntoIter = TokenTreeIter;
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700310
Alex Crichton1a7f7622017-07-05 17:47:15 -0700311 fn into_iter(self) -> TokenTreeIter {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700312 match self {
313 TokenStream::Nightly(tts) => TokenTreeIter::Nightly(tts.into_iter()),
314 TokenStream::Stable(tts) => TokenTreeIter::Stable(tts.into_iter()),
315 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700316 }
317}
318
Alex Crichton1a7f7622017-07-05 17:47:15 -0700319impl Iterator for TokenTreeIter {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700320 type Item = TokenTree;
321
322 fn next(&mut self) -> Option<TokenTree> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700323 let token = match self {
324 TokenTreeIter::Nightly(iter) => iter.next()?,
325 TokenTreeIter::Stable(iter) => return iter.next(),
326 };
Alex Crichton9cd80a62018-04-05 17:46:58 -0700327 Some(match token {
328 proc_macro::TokenTree::Group(tt) => {
329 let delim = match tt.delimiter() {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700330 proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
331 proc_macro::Delimiter::Bracket => Delimiter::Bracket,
332 proc_macro::Delimiter::Brace => Delimiter::Brace,
333 proc_macro::Delimiter::None => Delimiter::None,
334 };
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700335 let stream = ::TokenStream::_new(TokenStream::Nightly(tt.stream()));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700336 let mut g = Group::new(delim, stream);
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700337 g.set_span(::Span::_new(Span::Nightly(tt.span())));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700338 g.into()
339 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700340 proc_macro::TokenTree::Punct(tt) => {
Alex Crichton9cd80a62018-04-05 17:46:58 -0700341 let spacing = match tt.spacing() {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700342 proc_macro::Spacing::Joint => Spacing::Joint,
343 proc_macro::Spacing::Alone => Spacing::Alone,
344 };
Alex Crichtonf3888432018-05-16 09:11:05 -0700345 let mut o = Punct::new(tt.as_char(), spacing);
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700346 o.set_span(::Span::_new(Span::Nightly(tt.span())));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700347 o.into()
348 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700349 proc_macro::TokenTree::Ident(s) => ::Ident::_new(Ident::Nightly(s)).into(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700350 proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Nightly(l)).into(),
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700351 })
352 }
353
354 fn size_hint(&self) -> (usize, Option<usize>) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700355 match self {
356 TokenTreeIter::Nightly(tts) => tts.size_hint(),
357 TokenTreeIter::Stable(tts) => tts.size_hint(),
358 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700359 }
360}
361
Alex Crichton1a7f7622017-07-05 17:47:15 -0700362impl fmt::Debug for TokenTreeIter {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700363 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton1a7f7622017-07-05 17:47:15 -0700364 f.debug_struct("TokenTreeIter").finish()
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700365 }
366}
367
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700368pub use stable::FileName;
Nika Layzellb35a9a32017-12-30 14:34:35 -0500369
370// NOTE: We have to generate our own filename object here because we can't wrap
371// the one provided by proc_macro.
372#[derive(Clone, PartialEq, Eq)]
Alex Crichtonce0904d2018-08-27 17:29:49 -0700373#[cfg(super_unstable)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700374pub enum SourceFile {
375 Nightly(proc_macro::SourceFile, FileName),
376 Stable(stable::SourceFile),
377}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500378
Alex Crichtonce0904d2018-08-27 17:29:49 -0700379#[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500380impl SourceFile {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700381 fn nightly(sf: proc_macro::SourceFile) -> Self {
Alex Crichton9f0a28a2018-07-21 18:53:35 -0700382 let filename = stable::file_name(sf.path().display().to_string());
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700383 SourceFile::Nightly(sf, filename)
Nika Layzellb35a9a32017-12-30 14:34:35 -0500384 }
385
Nika Layzellf8d5f212017-12-11 14:07:02 -0500386 /// Get the path to this source file as a string.
Nika Layzellb35a9a32017-12-30 14:34:35 -0500387 pub fn path(&self) -> &FileName {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700388 match self {
389 SourceFile::Nightly(_, f) => f,
390 SourceFile::Stable(a) => a.path(),
391 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500392 }
393
394 pub fn is_real(&self) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700395 match self {
396 SourceFile::Nightly(a, _) => a.is_real(),
397 SourceFile::Stable(a) => a.is_real(),
398 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500399 }
400}
401
Alex Crichtonce0904d2018-08-27 17:29:49 -0700402#[cfg(super_unstable)]
Nika Layzellb35a9a32017-12-30 14:34:35 -0500403impl AsRef<FileName> for SourceFile {
404 fn as_ref(&self) -> &FileName {
405 self.path()
Nika Layzellf8d5f212017-12-11 14:07:02 -0500406 }
407}
408
Alex Crichtonce0904d2018-08-27 17:29:49 -0700409#[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500410impl fmt::Debug for SourceFile {
411 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700412 match self {
413 SourceFile::Nightly(a, _) => a.fmt(f),
414 SourceFile::Stable(a) => a.fmt(f),
415 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500416 }
417}
418
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500419pub struct LineColumn {
420 pub line: usize,
421 pub column: usize,
422}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500423
Alex Crichton9cd80a62018-04-05 17:46:58 -0700424#[derive(Copy, Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700425pub enum Span {
426 Nightly(proc_macro::Span),
427 Stable(stable::Span),
Sergio Benitez13805082018-01-04 01:25:45 -0800428}
429
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700430impl Span {
431 pub fn call_site() -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700432 if nightly_works() {
433 Span::Nightly(proc_macro::Span::call_site())
434 } else {
435 Span::Stable(stable::Span::call_site())
436 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700437 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700438
Alex Crichtonce0904d2018-08-27 17:29:49 -0700439 #[cfg(super_unstable)]
Alex Crichtone6085b72017-11-21 07:24:25 -0800440 pub fn def_site() -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700441 if nightly_works() {
442 Span::Nightly(proc_macro::Span::def_site())
443 } else {
444 Span::Stable(stable::Span::def_site())
445 }
Alex Crichton998f6422017-11-19 08:06:27 -0800446 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500447
Alex Crichtonce0904d2018-08-27 17:29:49 -0700448 #[cfg(super_unstable)]
David Tolnay4e8e3972018-01-05 18:10:22 -0800449 pub fn resolved_at(&self, other: Span) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700450 match (self, other) {
451 (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.resolved_at(b)),
452 (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.resolved_at(b)),
453 _ => mismatch(),
454 }
David Tolnay4e8e3972018-01-05 18:10:22 -0800455 }
456
Alex Crichtonce0904d2018-08-27 17:29:49 -0700457 #[cfg(super_unstable)]
David Tolnay4e8e3972018-01-05 18:10:22 -0800458 pub fn located_at(&self, other: Span) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700459 match (self, other) {
460 (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.located_at(b)),
461 (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.located_at(b)),
462 _ => mismatch(),
463 }
David Tolnay4e8e3972018-01-05 18:10:22 -0800464 }
465
David Tolnay16a17202017-12-31 10:47:24 -0500466 pub fn unstable(self) -> proc_macro::Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700467 match self {
468 Span::Nightly(s) => s,
469 Span::Stable(_) => mismatch(),
470 }
David Tolnay16a17202017-12-31 10:47:24 -0500471 }
472
Alex Crichtonce0904d2018-08-27 17:29:49 -0700473 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500474 pub fn source_file(&self) -> SourceFile {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700475 match self {
476 Span::Nightly(s) => SourceFile::nightly(s.source_file()),
477 Span::Stable(s) => SourceFile::Stable(s.source_file()),
478 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500479 }
480
Alex Crichtonce0904d2018-08-27 17:29:49 -0700481 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500482 pub fn start(&self) -> LineColumn {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700483 match self {
484 Span::Nightly(s) => {
485 let proc_macro::LineColumn { line, column } = s.start();
486 LineColumn { line, column }
487 }
488 Span::Stable(s) => {
489 let stable::LineColumn { line, column } = s.start();
490 LineColumn { line, column }
491 }
492 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500493 }
494
Alex Crichtonce0904d2018-08-27 17:29:49 -0700495 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500496 pub fn end(&self) -> LineColumn {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700497 match self {
498 Span::Nightly(s) => {
499 let proc_macro::LineColumn { line, column } = s.end();
500 LineColumn { line, column }
501 }
502 Span::Stable(s) => {
503 let stable::LineColumn { line, column } = s.end();
504 LineColumn { line, column }
505 }
506 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500507 }
508
Alex Crichtonce0904d2018-08-27 17:29:49 -0700509 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500510 pub fn join(&self, other: Span) -> Option<Span> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700511 let ret = match (self, other) {
512 (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.join(b)?),
513 (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.join(b)?),
514 _ => return None,
515 };
516 Some(ret)
Nika Layzellf8d5f212017-12-11 14:07:02 -0500517 }
Alex Crichtone24f7342018-04-05 17:58:11 -0700518
Alex Crichtonce0904d2018-08-27 17:29:49 -0700519 #[cfg(super_unstable)]
Alex Crichtone24f7342018-04-05 17:58:11 -0700520 pub fn eq(&self, other: &Span) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700521 match (self, other) {
522 (Span::Nightly(a), Span::Nightly(b)) => a.eq(b),
523 (Span::Stable(a), Span::Stable(b)) => a.eq(b),
524 _ => false,
525 }
526 }
527
528 fn unwrap_nightly(self) -> proc_macro::Span {
529 match self {
530 Span::Nightly(s) => s,
531 Span::Stable(_) => mismatch(),
532 }
533 }
534}
535
536impl From<proc_macro::Span> for ::Span {
537 fn from(proc_span: proc_macro::Span) -> ::Span {
538 ::Span::_new(Span::Nightly(proc_span))
539 }
540}
541
542impl From<stable::Span> for Span {
543 fn from(inner: stable::Span) -> Span {
544 Span::Stable(inner)
Alex Crichtone24f7342018-04-05 17:58:11 -0700545 }
Alex Crichton998f6422017-11-19 08:06:27 -0800546}
547
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700548impl fmt::Debug for Span {
549 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700550 match self {
551 Span::Nightly(s) => s.fmt(f),
552 Span::Stable(s) => s.fmt(f),
553 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700554 }
555}
556
Alex Crichtonf3888432018-05-16 09:11:05 -0700557#[derive(Clone)]
558pub enum Ident {
559 Nightly(proc_macro::Ident),
560 Stable(stable::Ident),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700561}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700562
Alex Crichtonf3888432018-05-16 09:11:05 -0700563impl Ident {
564 pub fn new(string: &str, span: Span) -> Ident {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700565 match span {
Alex Crichtonf3888432018-05-16 09:11:05 -0700566 Span::Nightly(s) => Ident::Nightly(proc_macro::Ident::new(string, s)),
567 Span::Stable(s) => Ident::Stable(stable::Ident::new(string, s)),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700568 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700569 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700570
Alex Crichtonf3888432018-05-16 09:11:05 -0700571 pub fn new_raw(string: &str, span: Span) -> Ident {
572 match span {
Alex Crichtonce0904d2018-08-27 17:29:49 -0700573 Span::Nightly(s) => {
574 let p: proc_macro::TokenStream = string.parse().unwrap();
575 let ident = match p.into_iter().next() {
576 Some(proc_macro::TokenTree::Ident(mut i)) => {
577 i.set_span(s);
578 i
579 }
580 _ => panic!(),
581 };
582 Ident::Nightly(ident)
583 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700584 Span::Stable(s) => Ident::Stable(stable::Ident::new_raw(string, s)),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700585 }
Alex Crichtonb2c94622018-04-04 07:36:41 -0700586 }
587
588 pub fn span(&self) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700589 match self {
Alex Crichtonf3888432018-05-16 09:11:05 -0700590 Ident::Nightly(t) => Span::Nightly(t.span()),
591 Ident::Stable(t) => Span::Stable(t.span()),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700592 }
Alex Crichtonb2c94622018-04-04 07:36:41 -0700593 }
594
595 pub fn set_span(&mut self, span: Span) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700596 match (self, span) {
Alex Crichtonf3888432018-05-16 09:11:05 -0700597 (Ident::Nightly(t), Span::Nightly(s)) => t.set_span(s),
598 (Ident::Stable(t), Span::Stable(s)) => t.set_span(s),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700599 _ => mismatch(),
600 }
601 }
602
Alex Crichtonf3888432018-05-16 09:11:05 -0700603 fn unwrap_nightly(self) -> proc_macro::Ident {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700604 match self {
Alex Crichtonf3888432018-05-16 09:11:05 -0700605 Ident::Nightly(s) => s,
606 Ident::Stable(_) => mismatch(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700607 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700608 }
609}
610
David Tolnayc0b0f2e2018-09-02 17:56:08 -0700611impl PartialEq for Ident {
612 fn eq(&self, other: &Ident) -> bool {
613 match (self, other) {
614 (Ident::Nightly(t), Ident::Nightly(o)) => t.to_string() == o.to_string(),
615 (Ident::Stable(t), Ident::Stable(o)) => t == o,
616 _ => mismatch(),
617 }
618 }
619}
620
621impl<T> PartialEq<T> for Ident
622where
623 T: ?Sized + AsRef<str>,
624{
625 fn eq(&self, other: &T) -> bool {
626 let other = other.as_ref();
627 match self {
628 Ident::Nightly(t) => t.to_string() == other,
629 Ident::Stable(t) => t == other,
630 }
631 }
632}
633
Alex Crichtonf3888432018-05-16 09:11:05 -0700634impl fmt::Display for Ident {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700635 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700636 match self {
Alex Crichtonf3888432018-05-16 09:11:05 -0700637 Ident::Nightly(t) => t.fmt(f),
638 Ident::Stable(t) => t.fmt(f),
639 }
640 }
641}
642
643impl fmt::Debug for Ident {
644 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
645 match self {
646 Ident::Nightly(t) => t.fmt(f),
647 Ident::Stable(t) => t.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700648 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700649 }
650}
651
652#[derive(Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700653pub enum Literal {
654 Nightly(proc_macro::Literal),
655 Stable(stable::Literal),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700656}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700657
Alex Crichtona914a612018-04-04 07:48:44 -0700658macro_rules! suffixed_numbers {
659 ($($name:ident => $kind:ident,)*) => ($(
660 pub fn $name(n: $kind) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700661 if nightly_works() {
662 Literal::Nightly(proc_macro::Literal::$name(n))
663 } else {
664 Literal::Stable(stable::Literal::$name(n))
665 }
Alex Crichtona914a612018-04-04 07:48:44 -0700666 }
667 )*)
668}
669
670macro_rules! unsuffixed_integers {
671 ($($name:ident => $kind:ident,)*) => ($(
672 pub fn $name(n: $kind) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700673 if nightly_works() {
674 Literal::Nightly(proc_macro::Literal::$name(n))
675 } else {
676 Literal::Stable(stable::Literal::$name(n))
677 }
Alex Crichtona914a612018-04-04 07:48:44 -0700678 }
679 )*)
680}
681
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700682impl Literal {
Alex Crichtona914a612018-04-04 07:48:44 -0700683 suffixed_numbers! {
684 u8_suffixed => u8,
685 u16_suffixed => u16,
686 u32_suffixed => u32,
687 u64_suffixed => u64,
688 usize_suffixed => usize,
689 i8_suffixed => i8,
690 i16_suffixed => i16,
691 i32_suffixed => i32,
692 i64_suffixed => i64,
693 isize_suffixed => isize,
694
695 f32_suffixed => f32,
696 f64_suffixed => f64,
697 }
698
699 unsuffixed_integers! {
700 u8_unsuffixed => u8,
701 u16_unsuffixed => u16,
702 u32_unsuffixed => u32,
703 u64_unsuffixed => u64,
704 usize_unsuffixed => usize,
705 i8_unsuffixed => i8,
706 i16_unsuffixed => i16,
707 i32_unsuffixed => i32,
708 i64_unsuffixed => i64,
709 isize_unsuffixed => isize,
710 }
711
712 pub fn f32_unsuffixed(f: f32) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700713 if nightly_works() {
714 Literal::Nightly(proc_macro::Literal::f32_unsuffixed(f))
715 } else {
716 Literal::Stable(stable::Literal::f32_unsuffixed(f))
717 }
Alex Crichtona914a612018-04-04 07:48:44 -0700718 }
719
720 pub fn f64_unsuffixed(f: f64) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700721 if nightly_works() {
722 Literal::Nightly(proc_macro::Literal::f64_unsuffixed(f))
723 } else {
724 Literal::Stable(stable::Literal::f64_unsuffixed(f))
725 }
Alex Crichtona914a612018-04-04 07:48:44 -0700726 }
727
Alex Crichtona914a612018-04-04 07:48:44 -0700728 pub fn string(t: &str) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700729 if nightly_works() {
730 Literal::Nightly(proc_macro::Literal::string(t))
731 } else {
732 Literal::Stable(stable::Literal::string(t))
733 }
Alex Crichtona914a612018-04-04 07:48:44 -0700734 }
735
736 pub fn character(t: char) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700737 if nightly_works() {
738 Literal::Nightly(proc_macro::Literal::character(t))
739 } else {
740 Literal::Stable(stable::Literal::character(t))
741 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700742 }
743
744 pub fn byte_string(bytes: &[u8]) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700745 if nightly_works() {
746 Literal::Nightly(proc_macro::Literal::byte_string(bytes))
747 } else {
748 Literal::Stable(stable::Literal::byte_string(bytes))
749 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700750 }
751
Alex Crichtonb2c94622018-04-04 07:36:41 -0700752 pub fn span(&self) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700753 match self {
754 Literal::Nightly(lit) => Span::Nightly(lit.span()),
755 Literal::Stable(lit) => Span::Stable(lit.span()),
756 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700757 }
758
Alex Crichtonb2c94622018-04-04 07:36:41 -0700759 pub fn set_span(&mut self, span: Span) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700760 match (self, span) {
761 (Literal::Nightly(lit), Span::Nightly(s)) => lit.set_span(s),
762 (Literal::Stable(lit), Span::Stable(s)) => lit.set_span(s),
763 _ => mismatch(),
764 }
765 }
766
767 fn unwrap_nightly(self) -> proc_macro::Literal {
768 match self {
769 Literal::Nightly(s) => s,
770 Literal::Stable(_) => mismatch(),
771 }
772 }
773}
774
775impl From<stable::Literal> for Literal {
776 fn from(s: stable::Literal) -> Literal {
777 Literal::Stable(s)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700778 }
779}
780
781impl fmt::Display for Literal {
782 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700783 match self {
784 Literal::Nightly(t) => t.fmt(f),
785 Literal::Stable(t) => t.fmt(f),
786 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700787 }
788}
789
790impl fmt::Debug for Literal {
791 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700792 match self {
793 Literal::Nightly(t) => t.fmt(f),
794 Literal::Stable(t) => t.fmt(f),
795 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700796 }
797}