blob: caf42ced6f9264a162b17a361318ce8f6fe2d6ff [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 Tolnay40d4ffd2018-08-12 13:49:09 -0700213 tts.extend(
214 streams
215 .into_iter()
216 .map(|t| TokenStream::from(t).unwrap_nightly()),
217 );
Alex Crichtonf3888432018-05-16 09:11:05 -0700218 }
219 TokenStream::Stable(tts) => tts.extend(streams),
220 }
221 }
222}
223
David Tolnay5c58c532018-08-13 11:33:51 -0700224impl Extend<TokenStream> for TokenStream {
225 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
226 match self {
227 TokenStream::Nightly(tts) => {
228 tts.extend(streams.into_iter().map(|stream| stream.unwrap_nightly()))
229 }
230 TokenStream::Stable(tts) => {
231 tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable()))
232 }
233 }
234 }
235}
236
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700237impl fmt::Debug for TokenStream {
238 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700239 match self {
240 TokenStream::Nightly(tts) => tts.fmt(f),
241 TokenStream::Stable(tts) => tts.fmt(f),
242 }
243 }
244}
245
246impl From<proc_macro::LexError> for LexError {
247 fn from(e: proc_macro::LexError) -> LexError {
248 LexError::Nightly(e)
249 }
250}
251
252impl From<stable::LexError> for LexError {
253 fn from(e: stable::LexError) -> LexError {
254 LexError::Stable(e)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700255 }
256}
257
258impl fmt::Debug for LexError {
259 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700260 match self {
261 LexError::Nightly(e) => e.fmt(f),
262 LexError::Stable(e) => e.fmt(f),
263 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700264 }
265}
266
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700267pub enum TokenTreeIter {
268 Nightly(proc_macro::token_stream::IntoIter),
269 Stable(stable::TokenTreeIter),
270}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700271
272impl IntoIterator for TokenStream {
273 type Item = TokenTree;
Alex Crichton1a7f7622017-07-05 17:47:15 -0700274 type IntoIter = TokenTreeIter;
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700275
Alex Crichton1a7f7622017-07-05 17:47:15 -0700276 fn into_iter(self) -> TokenTreeIter {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700277 match self {
278 TokenStream::Nightly(tts) => TokenTreeIter::Nightly(tts.into_iter()),
279 TokenStream::Stable(tts) => TokenTreeIter::Stable(tts.into_iter()),
280 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700281 }
282}
283
Alex Crichton1a7f7622017-07-05 17:47:15 -0700284impl Iterator for TokenTreeIter {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700285 type Item = TokenTree;
286
287 fn next(&mut self) -> Option<TokenTree> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700288 let token = match self {
289 TokenTreeIter::Nightly(iter) => iter.next()?,
290 TokenTreeIter::Stable(iter) => return iter.next(),
291 };
Alex Crichton9cd80a62018-04-05 17:46:58 -0700292 Some(match token {
293 proc_macro::TokenTree::Group(tt) => {
294 let delim = match tt.delimiter() {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700295 proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
296 proc_macro::Delimiter::Bracket => Delimiter::Bracket,
297 proc_macro::Delimiter::Brace => Delimiter::Brace,
298 proc_macro::Delimiter::None => Delimiter::None,
299 };
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700300 let stream = ::TokenStream::_new(TokenStream::Nightly(tt.stream()));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700301 let mut g = Group::new(delim, stream);
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700302 g.set_span(::Span::_new(Span::Nightly(tt.span())));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700303 g.into()
304 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700305 proc_macro::TokenTree::Punct(tt) => {
Alex Crichton9cd80a62018-04-05 17:46:58 -0700306 let spacing = match tt.spacing() {
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700307 proc_macro::Spacing::Joint => Spacing::Joint,
308 proc_macro::Spacing::Alone => Spacing::Alone,
309 };
Alex Crichtonf3888432018-05-16 09:11:05 -0700310 let mut o = Punct::new(tt.as_char(), spacing);
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700311 o.set_span(::Span::_new(Span::Nightly(tt.span())));
Alex Crichtonaf5bad42018-03-27 14:45:10 -0700312 o.into()
313 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700314 proc_macro::TokenTree::Ident(s) => ::Ident::_new(Ident::Nightly(s)).into(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700315 proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Nightly(l)).into(),
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700316 })
317 }
318
319 fn size_hint(&self) -> (usize, Option<usize>) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700320 match self {
321 TokenTreeIter::Nightly(tts) => tts.size_hint(),
322 TokenTreeIter::Stable(tts) => tts.size_hint(),
323 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700324 }
325}
326
Alex Crichton1a7f7622017-07-05 17:47:15 -0700327impl fmt::Debug for TokenTreeIter {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700328 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton1a7f7622017-07-05 17:47:15 -0700329 f.debug_struct("TokenTreeIter").finish()
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700330 }
331}
332
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700333pub use stable::FileName;
Nika Layzellb35a9a32017-12-30 14:34:35 -0500334
335// NOTE: We have to generate our own filename object here because we can't wrap
336// the one provided by proc_macro.
337#[derive(Clone, PartialEq, Eq)]
Alex Crichtonce0904d2018-08-27 17:29:49 -0700338#[cfg(super_unstable)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700339pub enum SourceFile {
340 Nightly(proc_macro::SourceFile, FileName),
341 Stable(stable::SourceFile),
342}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500343
Alex Crichtonce0904d2018-08-27 17:29:49 -0700344#[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500345impl SourceFile {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700346 fn nightly(sf: proc_macro::SourceFile) -> Self {
Alex Crichton9f0a28a2018-07-21 18:53:35 -0700347 let filename = stable::file_name(sf.path().display().to_string());
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700348 SourceFile::Nightly(sf, filename)
Nika Layzellb35a9a32017-12-30 14:34:35 -0500349 }
350
Nika Layzellf8d5f212017-12-11 14:07:02 -0500351 /// Get the path to this source file as a string.
Nika Layzellb35a9a32017-12-30 14:34:35 -0500352 pub fn path(&self) -> &FileName {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700353 match self {
354 SourceFile::Nightly(_, f) => f,
355 SourceFile::Stable(a) => a.path(),
356 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500357 }
358
359 pub fn is_real(&self) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700360 match self {
361 SourceFile::Nightly(a, _) => a.is_real(),
362 SourceFile::Stable(a) => a.is_real(),
363 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500364 }
365}
366
Alex Crichtonce0904d2018-08-27 17:29:49 -0700367#[cfg(super_unstable)]
Nika Layzellb35a9a32017-12-30 14:34:35 -0500368impl AsRef<FileName> for SourceFile {
369 fn as_ref(&self) -> &FileName {
370 self.path()
Nika Layzellf8d5f212017-12-11 14:07:02 -0500371 }
372}
373
Alex Crichtonce0904d2018-08-27 17:29:49 -0700374#[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500375impl fmt::Debug for SourceFile {
376 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700377 match self {
378 SourceFile::Nightly(a, _) => a.fmt(f),
379 SourceFile::Stable(a) => a.fmt(f),
380 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500381 }
382}
383
Nika Layzell1ecb6ce2017-12-30 14:34:05 -0500384pub struct LineColumn {
385 pub line: usize,
386 pub column: usize,
387}
Nika Layzellf8d5f212017-12-11 14:07:02 -0500388
Alex Crichton9cd80a62018-04-05 17:46:58 -0700389#[derive(Copy, Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700390pub enum Span {
391 Nightly(proc_macro::Span),
392 Stable(stable::Span),
Sergio Benitez13805082018-01-04 01:25:45 -0800393}
394
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700395impl Span {
396 pub fn call_site() -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700397 if nightly_works() {
398 Span::Nightly(proc_macro::Span::call_site())
399 } else {
400 Span::Stable(stable::Span::call_site())
401 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700402 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700403
Alex Crichtonce0904d2018-08-27 17:29:49 -0700404 #[cfg(super_unstable)]
Alex Crichtone6085b72017-11-21 07:24:25 -0800405 pub fn def_site() -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700406 if nightly_works() {
407 Span::Nightly(proc_macro::Span::def_site())
408 } else {
409 Span::Stable(stable::Span::def_site())
410 }
Alex Crichton998f6422017-11-19 08:06:27 -0800411 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500412
Alex Crichtonce0904d2018-08-27 17:29:49 -0700413 #[cfg(super_unstable)]
David Tolnay4e8e3972018-01-05 18:10:22 -0800414 pub fn resolved_at(&self, other: Span) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700415 match (self, other) {
416 (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.resolved_at(b)),
417 (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.resolved_at(b)),
418 _ => mismatch(),
419 }
David Tolnay4e8e3972018-01-05 18:10:22 -0800420 }
421
Alex Crichtonce0904d2018-08-27 17:29:49 -0700422 #[cfg(super_unstable)]
David Tolnay4e8e3972018-01-05 18:10:22 -0800423 pub fn located_at(&self, other: Span) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700424 match (self, other) {
425 (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.located_at(b)),
426 (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.located_at(b)),
427 _ => mismatch(),
428 }
David Tolnay4e8e3972018-01-05 18:10:22 -0800429 }
430
David Tolnay16a17202017-12-31 10:47:24 -0500431 pub fn unstable(self) -> proc_macro::Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700432 match self {
433 Span::Nightly(s) => s,
434 Span::Stable(_) => mismatch(),
435 }
David Tolnay16a17202017-12-31 10:47:24 -0500436 }
437
Alex Crichtonce0904d2018-08-27 17:29:49 -0700438 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500439 pub fn source_file(&self) -> SourceFile {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700440 match self {
441 Span::Nightly(s) => SourceFile::nightly(s.source_file()),
442 Span::Stable(s) => SourceFile::Stable(s.source_file()),
443 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500444 }
445
Alex Crichtonce0904d2018-08-27 17:29:49 -0700446 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500447 pub fn start(&self) -> LineColumn {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700448 match self {
449 Span::Nightly(s) => {
450 let proc_macro::LineColumn { line, column } = s.start();
451 LineColumn { line, column }
452 }
453 Span::Stable(s) => {
454 let stable::LineColumn { line, column } = s.start();
455 LineColumn { line, column }
456 }
457 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500458 }
459
Alex Crichtonce0904d2018-08-27 17:29:49 -0700460 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500461 pub fn end(&self) -> LineColumn {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700462 match self {
463 Span::Nightly(s) => {
464 let proc_macro::LineColumn { line, column } = s.end();
465 LineColumn { line, column }
466 }
467 Span::Stable(s) => {
468 let stable::LineColumn { line, column } = s.end();
469 LineColumn { line, column }
470 }
471 }
Nika Layzellf8d5f212017-12-11 14:07:02 -0500472 }
473
Alex Crichtonce0904d2018-08-27 17:29:49 -0700474 #[cfg(super_unstable)]
Nika Layzellf8d5f212017-12-11 14:07:02 -0500475 pub fn join(&self, other: Span) -> Option<Span> {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700476 let ret = match (self, other) {
477 (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.join(b)?),
478 (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.join(b)?),
479 _ => return None,
480 };
481 Some(ret)
Nika Layzellf8d5f212017-12-11 14:07:02 -0500482 }
Alex Crichtone24f7342018-04-05 17:58:11 -0700483
Alex Crichtonce0904d2018-08-27 17:29:49 -0700484 #[cfg(super_unstable)]
Alex Crichtone24f7342018-04-05 17:58:11 -0700485 pub fn eq(&self, other: &Span) -> bool {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700486 match (self, other) {
487 (Span::Nightly(a), Span::Nightly(b)) => a.eq(b),
488 (Span::Stable(a), Span::Stable(b)) => a.eq(b),
489 _ => false,
490 }
491 }
492
493 fn unwrap_nightly(self) -> proc_macro::Span {
494 match self {
495 Span::Nightly(s) => s,
496 Span::Stable(_) => mismatch(),
497 }
498 }
499}
500
501impl From<proc_macro::Span> for ::Span {
502 fn from(proc_span: proc_macro::Span) -> ::Span {
503 ::Span::_new(Span::Nightly(proc_span))
504 }
505}
506
507impl From<stable::Span> for Span {
508 fn from(inner: stable::Span) -> Span {
509 Span::Stable(inner)
Alex Crichtone24f7342018-04-05 17:58:11 -0700510 }
Alex Crichton998f6422017-11-19 08:06:27 -0800511}
512
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700513impl fmt::Debug for Span {
514 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700515 match self {
516 Span::Nightly(s) => s.fmt(f),
517 Span::Stable(s) => s.fmt(f),
518 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700519 }
520}
521
Alex Crichtonf3888432018-05-16 09:11:05 -0700522#[derive(Clone)]
523pub enum Ident {
524 Nightly(proc_macro::Ident),
525 Stable(stable::Ident),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700526}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700527
Alex Crichtonf3888432018-05-16 09:11:05 -0700528impl Ident {
529 pub fn new(string: &str, span: Span) -> Ident {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700530 match span {
Alex Crichtonf3888432018-05-16 09:11:05 -0700531 Span::Nightly(s) => Ident::Nightly(proc_macro::Ident::new(string, s)),
532 Span::Stable(s) => Ident::Stable(stable::Ident::new(string, s)),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700533 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700534 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700535
Alex Crichtonf3888432018-05-16 09:11:05 -0700536 pub fn new_raw(string: &str, span: Span) -> Ident {
537 match span {
Alex Crichtonce0904d2018-08-27 17:29:49 -0700538 Span::Nightly(s) => {
539 let p: proc_macro::TokenStream = string.parse().unwrap();
540 let ident = match p.into_iter().next() {
541 Some(proc_macro::TokenTree::Ident(mut i)) => {
542 i.set_span(s);
543 i
544 }
545 _ => panic!(),
546 };
547 Ident::Nightly(ident)
548 }
Alex Crichtonf3888432018-05-16 09:11:05 -0700549 Span::Stable(s) => Ident::Stable(stable::Ident::new_raw(string, s)),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700550 }
Alex Crichtonb2c94622018-04-04 07:36:41 -0700551 }
552
553 pub fn span(&self) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700554 match self {
Alex Crichtonf3888432018-05-16 09:11:05 -0700555 Ident::Nightly(t) => Span::Nightly(t.span()),
556 Ident::Stable(t) => Span::Stable(t.span()),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700557 }
Alex Crichtonb2c94622018-04-04 07:36:41 -0700558 }
559
560 pub fn set_span(&mut self, span: Span) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700561 match (self, span) {
Alex Crichtonf3888432018-05-16 09:11:05 -0700562 (Ident::Nightly(t), Span::Nightly(s)) => t.set_span(s),
563 (Ident::Stable(t), Span::Stable(s)) => t.set_span(s),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700564 _ => mismatch(),
565 }
566 }
567
Alex Crichtonf3888432018-05-16 09:11:05 -0700568 fn unwrap_nightly(self) -> proc_macro::Ident {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700569 match self {
Alex Crichtonf3888432018-05-16 09:11:05 -0700570 Ident::Nightly(s) => s,
571 Ident::Stable(_) => mismatch(),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700572 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700573 }
574}
575
David Tolnayc0b0f2e2018-09-02 17:56:08 -0700576impl PartialEq for Ident {
577 fn eq(&self, other: &Ident) -> bool {
578 match (self, other) {
579 (Ident::Nightly(t), Ident::Nightly(o)) => t.to_string() == o.to_string(),
580 (Ident::Stable(t), Ident::Stable(o)) => t == o,
581 _ => mismatch(),
582 }
583 }
584}
585
586impl<T> PartialEq<T> for Ident
587where
588 T: ?Sized + AsRef<str>,
589{
590 fn eq(&self, other: &T) -> bool {
591 let other = other.as_ref();
592 match self {
593 Ident::Nightly(t) => t.to_string() == other,
594 Ident::Stable(t) => t == other,
595 }
596 }
597}
598
Alex Crichtonf3888432018-05-16 09:11:05 -0700599impl fmt::Display for Ident {
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700600 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700601 match self {
Alex Crichtonf3888432018-05-16 09:11:05 -0700602 Ident::Nightly(t) => t.fmt(f),
603 Ident::Stable(t) => t.fmt(f),
604 }
605 }
606}
607
608impl fmt::Debug for Ident {
609 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
610 match self {
611 Ident::Nightly(t) => t.fmt(f),
612 Ident::Stable(t) => t.fmt(f),
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700613 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700614 }
615}
616
617#[derive(Clone)]
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700618pub enum Literal {
619 Nightly(proc_macro::Literal),
620 Stable(stable::Literal),
Alex Crichtonb2c94622018-04-04 07:36:41 -0700621}
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700622
Alex Crichtona914a612018-04-04 07:48:44 -0700623macro_rules! suffixed_numbers {
624 ($($name:ident => $kind:ident,)*) => ($(
625 pub fn $name(n: $kind) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700626 if nightly_works() {
627 Literal::Nightly(proc_macro::Literal::$name(n))
628 } else {
629 Literal::Stable(stable::Literal::$name(n))
630 }
Alex Crichtona914a612018-04-04 07:48:44 -0700631 }
632 )*)
633}
634
635macro_rules! unsuffixed_integers {
636 ($($name:ident => $kind:ident,)*) => ($(
637 pub fn $name(n: $kind) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700638 if nightly_works() {
639 Literal::Nightly(proc_macro::Literal::$name(n))
640 } else {
641 Literal::Stable(stable::Literal::$name(n))
642 }
Alex Crichtona914a612018-04-04 07:48:44 -0700643 }
644 )*)
645}
646
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700647impl Literal {
Alex Crichtona914a612018-04-04 07:48:44 -0700648 suffixed_numbers! {
649 u8_suffixed => u8,
650 u16_suffixed => u16,
651 u32_suffixed => u32,
652 u64_suffixed => u64,
653 usize_suffixed => usize,
654 i8_suffixed => i8,
655 i16_suffixed => i16,
656 i32_suffixed => i32,
657 i64_suffixed => i64,
658 isize_suffixed => isize,
659
660 f32_suffixed => f32,
661 f64_suffixed => f64,
662 }
663
664 unsuffixed_integers! {
665 u8_unsuffixed => u8,
666 u16_unsuffixed => u16,
667 u32_unsuffixed => u32,
668 u64_unsuffixed => u64,
669 usize_unsuffixed => usize,
670 i8_unsuffixed => i8,
671 i16_unsuffixed => i16,
672 i32_unsuffixed => i32,
673 i64_unsuffixed => i64,
674 isize_unsuffixed => isize,
675 }
676
677 pub fn f32_unsuffixed(f: f32) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700678 if nightly_works() {
679 Literal::Nightly(proc_macro::Literal::f32_unsuffixed(f))
680 } else {
681 Literal::Stable(stable::Literal::f32_unsuffixed(f))
682 }
Alex Crichtona914a612018-04-04 07:48:44 -0700683 }
684
685 pub fn f64_unsuffixed(f: f64) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700686 if nightly_works() {
687 Literal::Nightly(proc_macro::Literal::f64_unsuffixed(f))
688 } else {
689 Literal::Stable(stable::Literal::f64_unsuffixed(f))
690 }
Alex Crichtona914a612018-04-04 07:48:44 -0700691 }
692
Alex Crichtona914a612018-04-04 07:48:44 -0700693 pub fn string(t: &str) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700694 if nightly_works() {
695 Literal::Nightly(proc_macro::Literal::string(t))
696 } else {
697 Literal::Stable(stable::Literal::string(t))
698 }
Alex Crichtona914a612018-04-04 07:48:44 -0700699 }
700
701 pub fn character(t: char) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700702 if nightly_works() {
703 Literal::Nightly(proc_macro::Literal::character(t))
704 } else {
705 Literal::Stable(stable::Literal::character(t))
706 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700707 }
708
709 pub fn byte_string(bytes: &[u8]) -> Literal {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700710 if nightly_works() {
711 Literal::Nightly(proc_macro::Literal::byte_string(bytes))
712 } else {
713 Literal::Stable(stable::Literal::byte_string(bytes))
714 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700715 }
716
Alex Crichtonb2c94622018-04-04 07:36:41 -0700717 pub fn span(&self) -> Span {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700718 match self {
719 Literal::Nightly(lit) => Span::Nightly(lit.span()),
720 Literal::Stable(lit) => Span::Stable(lit.span()),
721 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700722 }
723
Alex Crichtonb2c94622018-04-04 07:36:41 -0700724 pub fn set_span(&mut self, span: Span) {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700725 match (self, span) {
726 (Literal::Nightly(lit), Span::Nightly(s)) => lit.set_span(s),
727 (Literal::Stable(lit), Span::Stable(s)) => lit.set_span(s),
728 _ => mismatch(),
729 }
730 }
731
732 fn unwrap_nightly(self) -> proc_macro::Literal {
733 match self {
734 Literal::Nightly(s) => s,
735 Literal::Stable(_) => mismatch(),
736 }
737 }
738}
739
740impl From<stable::Literal> for Literal {
741 fn from(s: stable::Literal) -> Literal {
742 Literal::Stable(s)
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700743 }
744}
745
746impl fmt::Display for Literal {
747 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700748 match self {
749 Literal::Nightly(t) => t.fmt(f),
750 Literal::Stable(t) => t.fmt(f),
751 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700752 }
753}
754
755impl fmt::Debug for Literal {
756 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Alex Crichton30a4e9e2018-04-27 17:02:19 -0700757 match self {
758 Literal::Nightly(t) => t.fmt(f),
759 Literal::Stable(t) => t.fmt(f),
760 }
Alex Crichtoncbec8ec2017-06-02 13:19:33 -0700761 }
762}