1 //! lib-proc-macro main module
2 //!
3 //! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/lib.rs>
4 //! augmented with removing unstable features
5 
6 // NOTE(@edwin0cheng):
7 // Because we just copy the bridge module from rustc for ABI compatible
8 // There are some unused stuffs inside it.
9 // We suppress these warning here.
10 #[doc(hidden)]
11 #[allow(unused_macros)]
12 #[allow(unused_variables)]
13 pub mod bridge;
14 
15 mod diagnostic;
16 
17 pub use diagnostic::{Diagnostic, Level, MultiSpan};
18 
19 use std::ops::{Bound, RangeBounds};
20 use std::path::PathBuf;
21 use std::str::FromStr;
22 use std::{fmt, iter, mem};
23 
24 /// The main type provided by this crate, representing an abstract stream of
25 /// tokens, or, more specifically, a sequence of token trees.
26 /// The type provide interfaces for iterating over those token trees and, conversely,
27 /// collecting a number of token trees into one stream.
28 ///
29 /// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]`
30 /// and `#[proc_macro_derive]` definitions.
31 #[derive(Clone)]
32 pub struct TokenStream(bridge::client::TokenStream);
33 
34 /// Error returned from `TokenStream::from_str`
35 #[derive(Debug)]
36 pub struct LexError {
37     _inner: (),
38 }
39 impl LexError {
new() -> Self40     fn new() -> Self {
41         LexError { _inner: () }
42     }
43 }
44 
45 impl TokenStream {
46     /// Returns an empty `TokenStream` containing no token trees.
new() -> TokenStream47     pub fn new() -> TokenStream {
48         TokenStream(bridge::client::TokenStream::new())
49     }
50 
51     /// Checks if this `TokenStream` is empty.
is_empty(&self) -> bool52     pub fn is_empty(&self) -> bool {
53         self.0.is_empty()
54     }
55 }
56 
57 /// Attempts to break the string into tokens and parse those tokens into a token stream.
58 /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
59 /// or characters not existing in the language.
60 /// All tokens in the parsed stream get `Span::call_site()` spans.
61 ///
62 /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to
63 /// change these errors into `LexError`s later.
64 impl FromStr for TokenStream {
65     type Err = LexError;
66 
from_str(src: &str) -> Result<TokenStream, LexError>67     fn from_str(src: &str) -> Result<TokenStream, LexError> {
68         Ok(TokenStream(bridge::client::TokenStream::from_str(src)))
69     }
70 }
71 
72 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
73 // based on it (the reverse of the usual relationship between the two).
74 // impl ToString for TokenStream {
75 //     fn to_string(&self) -> String {
76 //         self.0.to_string()
77 //     }
78 // }
79 
80 /// Prints the token stream as a string that is supposed to be losslessly convertible back
81 /// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s
82 /// with `Delimiter::None` delimiters and negative numeric literals.
83 impl fmt::Display for TokenStream {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result84     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85         f.write_str(&self.to_string())
86     }
87 }
88 
89 /// Prints token in a form convenient for debugging.
90 impl fmt::Debug for TokenStream {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result91     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92         f.write_str("TokenStream ")?;
93         f.debug_list().entries(self.clone()).finish()
94     }
95 }
96 
97 /// Creates a token stream containing a single token tree.
98 impl From<TokenTree> for TokenStream {
from(tree: TokenTree) -> TokenStream99     fn from(tree: TokenTree) -> TokenStream {
100         TokenStream(bridge::client::TokenStream::from_token_tree(match tree {
101             TokenTree::Group(tt) => bridge::TokenTree::Group(tt.0),
102             TokenTree::Punct(tt) => bridge::TokenTree::Punct(tt.0),
103             TokenTree::Ident(tt) => bridge::TokenTree::Ident(tt.0),
104             TokenTree::Literal(tt) => bridge::TokenTree::Literal(tt.0),
105         }))
106     }
107 }
108 
109 /// Collects a number of token trees into a single stream.
110 impl iter::FromIterator<TokenTree> for TokenStream {
from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self111     fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
112         trees.into_iter().map(TokenStream::from).collect()
113     }
114 }
115 
116 /// A "flattening" operation on token streams, collects token trees
117 /// from multiple token streams into a single stream.
118 impl iter::FromIterator<TokenStream> for TokenStream {
from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self119     fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
120         let mut builder = bridge::client::TokenStreamBuilder::new();
121         streams.into_iter().for_each(|stream| builder.push(stream.0));
122         TokenStream(builder.build())
123     }
124 }
125 
126 impl Extend<TokenTree> for TokenStream {
extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I)127     fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
128         self.extend(trees.into_iter().map(TokenStream::from));
129     }
130 }
131 
132 impl Extend<TokenStream> for TokenStream {
extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I)133     fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
134         // FIXME(eddyb) Use an optimized implementation if/when possible.
135         *self = iter::once(mem::replace(self, Self::new())).chain(streams).collect();
136     }
137 }
138 
139 /// Public implementation details for the `TokenStream` type, such as iterators.
140 pub mod token_stream {
141     use super::{bridge, Group, Ident, Literal, Punct, TokenStream, TokenTree};
142 
143     /// An iterator over `TokenStream`'s `TokenTree`s.
144     /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
145     /// and returns whole groups as token trees.
146     #[derive(Clone)]
147     pub struct IntoIter(bridge::client::TokenStreamIter);
148 
149     impl Iterator for IntoIter {
150         type Item = TokenTree;
151 
next(&mut self) -> Option<TokenTree>152         fn next(&mut self) -> Option<TokenTree> {
153             self.0.next().map(|tree| match tree {
154                 bridge::TokenTree::Group(tt) => TokenTree::Group(Group(tt)),
155                 bridge::TokenTree::Punct(tt) => TokenTree::Punct(Punct(tt)),
156                 bridge::TokenTree::Ident(tt) => TokenTree::Ident(Ident(tt)),
157                 bridge::TokenTree::Literal(tt) => TokenTree::Literal(Literal(tt)),
158             })
159         }
160     }
161 
162     impl IntoIterator for TokenStream {
163         type Item = TokenTree;
164         type IntoIter = IntoIter;
165 
into_iter(self) -> IntoIter166         fn into_iter(self) -> IntoIter {
167             IntoIter(self.0.into_iter())
168         }
169     }
170 }
171 
172 /// A region of source code, along with macro expansion information.
173 #[derive(Copy, Clone)]
174 pub struct Span(bridge::client::Span);
175 
176 macro_rules! diagnostic_method {
177     ($name:ident, $level:expr) => {
178         /// Creates a new `Diagnostic` with the given `message` at the span
179         /// `self`.
180         pub fn $name<T: Into<String>>(self, message: T) -> Diagnostic {
181             Diagnostic::spanned(self, $level, message)
182         }
183     };
184 }
185 
186 impl Span {
187     /// A span that resolves at the macro definition site.
def_site() -> Span188     pub fn def_site() -> Span {
189         Span(bridge::client::Span::def_site())
190     }
191 
192     /// The span of the invocation of the current procedural macro.
193     /// Identifiers created with this span will be resolved as if they were written
194     /// directly at the macro call location (call-site hygiene) and other code
195     /// at the macro call site will be able to refer to them as well.
call_site() -> Span196     pub fn call_site() -> Span {
197         Span(bridge::client::Span::call_site())
198     }
199 
200     /// A span that represents `macro_rules` hygiene, and sometimes resolves at the macro
201     /// definition site (local variables, labels, `$crate`) and sometimes at the macro
202     /// call site (everything else).
203     /// The span location is taken from the call-site.
mixed_site() -> Span204     pub fn mixed_site() -> Span {
205         Span(bridge::client::Span::mixed_site())
206     }
207 
208     /// The original source file into which this span points.
source_file(&self) -> SourceFile209     pub fn source_file(&self) -> SourceFile {
210         SourceFile(self.0.source_file())
211     }
212 
213     /// The `Span` for the tokens in the previous macro expansion from which
214     /// `self` was generated from, if any.
parent(&self) -> Option<Span>215     pub fn parent(&self) -> Option<Span> {
216         self.0.parent().map(Span)
217     }
218 
219     /// The span for the origin source code that `self` was generated from. If
220     /// this `Span` wasn't generated from other macro expansions then the return
221     /// value is the same as `*self`.
source(&self) -> Span222     pub fn source(&self) -> Span {
223         Span(self.0.source())
224     }
225 
226     /// Gets the starting line/column in the source file for this span.
start(&self) -> LineColumn227     pub fn start(&self) -> LineColumn {
228         self.0.start()
229     }
230 
231     /// Gets the ending line/column in the source file for this span.
end(&self) -> LineColumn232     pub fn end(&self) -> LineColumn {
233         self.0.end()
234     }
235 
236     /// Creates a new span encompassing `self` and `other`.
237     ///
238     /// Returns `None` if `self` and `other` are from different files.
join(&self, other: Span) -> Option<Span>239     pub fn join(&self, other: Span) -> Option<Span> {
240         self.0.join(other.0).map(Span)
241     }
242 
243     /// Creates a new span with the same line/column information as `self` but
244     /// that resolves symbols as though it were at `other`.
resolved_at(&self, other: Span) -> Span245     pub fn resolved_at(&self, other: Span) -> Span {
246         Span(self.0.resolved_at(other.0))
247     }
248 
249     /// Creates a new span with the same name resolution behavior as `self` but
250     /// with the line/column information of `other`.
located_at(&self, other: Span) -> Span251     pub fn located_at(&self, other: Span) -> Span {
252         other.resolved_at(*self)
253     }
254 
255     /// Compares to spans to see if they're equal.
eq(&self, other: &Span) -> bool256     pub fn eq(&self, other: &Span) -> bool {
257         self.0 == other.0
258     }
259 
260     /// Returns the source text behind a span. This preserves the original source
261     /// code, including spaces and comments. It only returns a result if the span
262     /// corresponds to real source code.
263     ///
264     /// Note: The observable result of a macro should only rely on the tokens and
265     /// not on this source text. The result of this function is a best effort to
266     /// be used for diagnostics only.
source_text(&self) -> Option<String>267     pub fn source_text(&self) -> Option<String> {
268         self.0.source_text()
269     }
270 
271     diagnostic_method!(error, Level::Error);
272     diagnostic_method!(warning, Level::Warning);
273     diagnostic_method!(note, Level::Note);
274     diagnostic_method!(help, Level::Help);
275 }
276 
277 /// Prints a span in a form convenient for debugging.
278 impl fmt::Debug for Span {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result279     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280         self.0.fmt(f)
281     }
282 }
283 
284 /// A line-column pair representing the start or end of a `Span`.
285 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
286 pub struct LineColumn {
287     /// The 1-indexed line in the source file on which the span starts or ends (inclusive).
288     pub line: usize,
289     /// The 0-indexed column (in UTF-8 characters) in the source file on which
290     /// the span starts or ends (inclusive).
291     pub column: usize,
292 }
293 
294 /// The source file of a given `Span`.
295 #[derive(Clone)]
296 pub struct SourceFile(bridge::client::SourceFile);
297 
298 impl SourceFile {
299     /// Gets the path to this source file.
300     ///
301     /// ### Note
302     /// If the code span associated with this `SourceFile` was generated by an external macro, this
303     /// macro, this may not be an actual path on the filesystem. Use [`is_real`] to check.
304     ///
305     /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on
306     /// the command line, the path as given may not actually be valid.
307     ///
308     /// [`is_real`]: #method.is_real
path(&self) -> PathBuf309     pub fn path(&self) -> PathBuf {
310         PathBuf::from(self.0.path())
311     }
312 
313     /// Returns `true` if this source file is a real source file, and not generated by an external
314     /// macro's expansion.
is_real(&self) -> bool315     pub fn is_real(&self) -> bool {
316         // This is a hack until intercrate spans are implemented and we can have real source files
317         // for spans generated in external macros.
318         // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368
319         self.0.is_real()
320     }
321 }
322 
323 impl fmt::Debug for SourceFile {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result324     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
325         f.debug_struct("SourceFile")
326             .field("path", &self.path())
327             .field("is_real", &self.is_real())
328             .finish()
329     }
330 }
331 
332 impl PartialEq for SourceFile {
eq(&self, other: &Self) -> bool333     fn eq(&self, other: &Self) -> bool {
334         self.0.eq(&other.0)
335     }
336 }
337 
338 impl Eq for SourceFile {}
339 
340 /// A single token or a delimited sequence of token trees (e.g., `[1, (), ..]`).
341 #[derive(Clone)]
342 pub enum TokenTree {
343     /// A token stream surrounded by bracket delimiters.
344     Group(Group),
345     /// An identifier.
346     Ident(Ident),
347     /// A single punctuation character (`+`, `,`, `$`, etc.).
348     Punct(Punct),
349     /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc.
350     Literal(Literal),
351 }
352 
353 impl TokenTree {
354     /// Returns the span of this tree, delegating to the `span` method of
355     /// the contained token or a delimited stream.
span(&self) -> Span356     pub fn span(&self) -> Span {
357         match *self {
358             TokenTree::Group(ref t) => t.span(),
359             TokenTree::Ident(ref t) => t.span(),
360             TokenTree::Punct(ref t) => t.span(),
361             TokenTree::Literal(ref t) => t.span(),
362         }
363     }
364 
365     /// Configures the span for *only this token*.
366     ///
367     /// Note that if this token is a `Group` then this method will not configure
368     /// the span of each of the internal tokens, this will simply delegate to
369     /// the `set_span` method of each variant.
set_span(&mut self, span: Span)370     pub fn set_span(&mut self, span: Span) {
371         match *self {
372             TokenTree::Group(ref mut t) => t.set_span(span),
373             TokenTree::Ident(ref mut t) => t.set_span(span),
374             TokenTree::Punct(ref mut t) => t.set_span(span),
375             TokenTree::Literal(ref mut t) => t.set_span(span),
376         }
377     }
378 }
379 
380 /// Prints token tree in a form convenient for debugging.
381 impl fmt::Debug for TokenTree {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result382     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383         // Each of these has the name in the struct type in the derived debug,
384         // so don't bother with an extra layer of indirection
385         match *self {
386             TokenTree::Group(ref tt) => tt.fmt(f),
387             TokenTree::Ident(ref tt) => tt.fmt(f),
388             TokenTree::Punct(ref tt) => tt.fmt(f),
389             TokenTree::Literal(ref tt) => tt.fmt(f),
390         }
391     }
392 }
393 
394 impl From<Group> for TokenTree {
from(g: Group) -> TokenTree395     fn from(g: Group) -> TokenTree {
396         TokenTree::Group(g)
397     }
398 }
399 
400 impl From<Ident> for TokenTree {
from(g: Ident) -> TokenTree401     fn from(g: Ident) -> TokenTree {
402         TokenTree::Ident(g)
403     }
404 }
405 
406 impl From<Punct> for TokenTree {
from(g: Punct) -> TokenTree407     fn from(g: Punct) -> TokenTree {
408         TokenTree::Punct(g)
409     }
410 }
411 
412 impl From<Literal> for TokenTree {
from(g: Literal) -> TokenTree413     fn from(g: Literal) -> TokenTree {
414         TokenTree::Literal(g)
415     }
416 }
417 
418 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
419 // based on it (the reverse of the usual relationship between the two).
420 // impl ToString for TokenTree {
421 //     fn to_string(&self) -> String {
422 //         match *self {
423 //             TokenTree::Group(ref t) => t.to_string(),
424 //             TokenTree::Ident(ref t) => t.to_string(),
425 //             TokenTree::Punct(ref t) => t.to_string(),
426 //             TokenTree::Literal(ref t) => t.to_string(),
427 //         }
428 //     }
429 // }
430 
431 /// Prints the token tree as a string that is supposed to be losslessly convertible back
432 /// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s
433 /// with `Delimiter::None` delimiters and negative numeric literals.
434 impl fmt::Display for TokenTree {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result435     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
436         f.write_str(&self.to_string())
437     }
438 }
439 
440 /// A delimited token stream.
441 ///
442 /// A `Group` internally contains a `TokenStream` which is surrounded by `Delimiter`s.
443 #[derive(Clone)]
444 pub struct Group(bridge::client::Group);
445 
446 /// Describes how a sequence of token trees is delimited.
447 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
448 pub enum Delimiter {
449     /// `( ... )`
450     Parenthesis,
451     /// `{ ... }`
452     Brace,
453     /// `[ ... ]`
454     Bracket,
455     /// `Ø ... Ø`
456     /// An implicit delimiter, that may, for example, appear around tokens coming from a
457     /// "macro variable" `$var`. It is important to preserve operator priorities in cases like
458     /// `$var * 3` where `$var` is `1 + 2`.
459     /// Implicit delimiters may not survive roundtrip of a token stream through a string.
460     None,
461 }
462 
463 impl Group {
464     /// Creates a new `Group` with the given delimiter and token stream.
465     ///
466     /// This constructor will set the span for this group to
467     /// `Span::call_site()`. To change the span you can use the `set_span`
468     /// method below.
new(delimiter: Delimiter, stream: TokenStream) -> Group469     pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
470         Group(bridge::client::Group::new(delimiter, stream.0))
471     }
472 
473     /// Returns the delimiter of this `Group`
delimiter(&self) -> Delimiter474     pub fn delimiter(&self) -> Delimiter {
475         self.0.delimiter()
476     }
477 
478     /// Returns the `TokenStream` of tokens that are delimited in this `Group`.
479     ///
480     /// Note that the returned token stream does not include the delimiter
481     /// returned above.
stream(&self) -> TokenStream482     pub fn stream(&self) -> TokenStream {
483         TokenStream(self.0.stream())
484     }
485 
486     /// Returns the span for the delimiters of this token stream, spanning the
487     /// entire `Group`.
488     ///
489     /// ```text
490     /// pub fn span(&self) -> Span {
491     ///            ^^^^^^^
492     /// ```
span(&self) -> Span493     pub fn span(&self) -> Span {
494         Span(self.0.span())
495     }
496 
497     /// Returns the span pointing to the opening delimiter of this group.
498     ///
499     /// ```text
500     /// pub fn span_open(&self) -> Span {
501     ///                 ^
502     /// ```
span_open(&self) -> Span503     pub fn span_open(&self) -> Span {
504         Span(self.0.span_open())
505     }
506 
507     /// Returns the span pointing to the closing delimiter of this group.
508     ///
509     /// ```text
510     /// pub fn span_close(&self) -> Span {
511     ///                        ^
512     /// ```
span_close(&self) -> Span513     pub fn span_close(&self) -> Span {
514         Span(self.0.span_close())
515     }
516 
517     /// Configures the span for this `Group`'s delimiters, but not its internal
518     /// tokens.
519     ///
520     /// This method will **not** set the span of all the internal tokens spanned
521     /// by this group, but rather it will only set the span of the delimiter
522     /// tokens at the level of the `Group`.
set_span(&mut self, span: Span)523     pub fn set_span(&mut self, span: Span) {
524         self.0.set_span(span.0);
525     }
526 }
527 
528 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
529 // based on it (the reverse of the usual relationship between the two).
530 // impl ToString for Group {
531 //     fn to_string(&self) -> String {
532 //         TokenStream::from(TokenTree::from(self.clone())).to_string()
533 //     }
534 // }
535 
536 /// Prints the group as a string that should be losslessly convertible back
537 /// into the same group (modulo spans), except for possibly `TokenTree::Group`s
538 /// with `Delimiter::None` delimiters.
539 impl fmt::Display for Group {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result540     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541         f.write_str(&self.to_string())
542     }
543 }
544 
545 impl fmt::Debug for Group {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result546     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
547         f.debug_struct("Group")
548             .field("delimiter", &self.delimiter())
549             .field("stream", &self.stream())
550             .field("span", &self.span())
551             .finish()
552     }
553 }
554 
555 /// An `Punct` is an single punctuation character like `+`, `-` or `#`.
556 ///
557 /// Multi-character operators like `+=` are represented as two instances of `Punct` with different
558 /// forms of `Spacing` returned.
559 #[derive(Clone)]
560 pub struct Punct(bridge::client::Punct);
561 
562 /// Whether an `Punct` is followed immediately by another `Punct` or
563 /// followed by another token or whitespace.
564 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
565 pub enum Spacing {
566     /// e.g., `+` is `Alone` in `+ =`, `+ident` or `+()`.
567     Alone,
568     /// e.g., `+` is `Joint` in `+=` or `'#`.
569     /// Additionally, single quote `'` can join with identifiers to form lifetimes `'ident`.
570     Joint,
571 }
572 
573 impl Punct {
574     /// Creates a new `Punct` from the given character and spacing.
575     /// The `ch` argument must be a valid punctuation character permitted by the language,
576     /// otherwise the function will panic.
577     ///
578     /// The returned `Punct` will have the default span of `Span::call_site()`
579     /// which can be further configured with the `set_span` method below.
new(ch: char, spacing: Spacing) -> Punct580     pub fn new(ch: char, spacing: Spacing) -> Punct {
581         Punct(bridge::client::Punct::new(ch, spacing))
582     }
583 
584     /// Returns the value of this punctuation character as `char`.
as_char(&self) -> char585     pub fn as_char(&self) -> char {
586         self.0.as_char()
587     }
588 
589     /// Returns the spacing of this punctuation character, indicating whether it's immediately
590     /// followed by another `Punct` in the token stream, so they can potentially be combined into
591     /// a multi-character operator (`Joint`), or it's followed by some other token or whitespace
592     /// (`Alone`) so the operator has certainly ended.
spacing(&self) -> Spacing593     pub fn spacing(&self) -> Spacing {
594         self.0.spacing()
595     }
596 
597     /// Returns the span for this punctuation character.
span(&self) -> Span598     pub fn span(&self) -> Span {
599         Span(self.0.span())
600     }
601 
602     /// Configure the span for this punctuation character.
set_span(&mut self, span: Span)603     pub fn set_span(&mut self, span: Span) {
604         self.0 = self.0.with_span(span.0);
605     }
606 }
607 
608 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
609 // based on it (the reverse of the usual relationship between the two).
610 // impl ToString for Punct {
611 //     fn to_string(&self) -> String {
612 //         TokenStream::from(TokenTree::from(self.clone())).to_string()
613 //     }
614 // }
615 
616 /// Prints the punctuation character as a string that should be losslessly convertible
617 /// back into the same character.
618 impl fmt::Display for Punct {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result619     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
620         f.write_str(&self.to_string())
621     }
622 }
623 
624 impl fmt::Debug for Punct {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result625     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
626         f.debug_struct("Punct")
627             .field("ch", &self.as_char())
628             .field("spacing", &self.spacing())
629             .field("span", &self.span())
630             .finish()
631     }
632 }
633 
634 /// An identifier (`ident`).
635 #[derive(Clone, PartialEq, Eq, Hash)]
636 pub struct Ident(bridge::client::Ident);
637 
638 impl Ident {
639     /// Creates a new `Ident` with the given `string` as well as the specified
640     /// `span`.
641     /// The `string` argument must be a valid identifier permitted by the
642     /// language, otherwise the function will panic.
643     ///
644     /// Note that `span`, currently in rustc, configures the hygiene information
645     /// for this identifier.
646     ///
647     /// As of this time `Span::call_site()` explicitly opts-in to "call-site" hygiene
648     /// meaning that identifiers created with this span will be resolved as if they were written
649     /// directly at the location of the macro call, and other code at the macro call site will be
650     /// able to refer to them as well.
651     ///
652     /// Later spans like `Span::def_site()` will allow to opt-in to "definition-site" hygiene
653     /// meaning that identifiers created with this span will be resolved at the location of the
654     /// macro definition and other code at the macro call site will not be able to refer to them.
655     ///
656     /// Due to the current importance of hygiene this constructor, unlike other
657     /// tokens, requires a `Span` to be specified at construction.
new(string: &str, span: Span) -> Ident658     pub fn new(string: &str, span: Span) -> Ident {
659         Ident(bridge::client::Ident::new(string, span.0, false))
660     }
661 
662     /// Same as `Ident::new`, but creates a raw identifier (`r#ident`).
new_raw(string: &str, span: Span) -> Ident663     pub fn new_raw(string: &str, span: Span) -> Ident {
664         Ident(bridge::client::Ident::new(string, span.0, true))
665     }
666 
667     /// Returns the span of this `Ident`, encompassing the entire string returned
668     /// by `as_str`.
span(&self) -> Span669     pub fn span(&self) -> Span {
670         Span(self.0.span())
671     }
672 
673     /// Configures the span of this `Ident`, possibly changing its hygiene context.
set_span(&mut self, span: Span)674     pub fn set_span(&mut self, span: Span) {
675         self.0 = self.0.with_span(span.0);
676     }
677 }
678 
679 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
680 // based on it (the reverse of the usual relationship between the two).
681 // impl ToString for Ident {
682 //     fn to_string(&self) -> String {
683 //         TokenStream::from(TokenTree::from(self.clone())).to_string()
684 //     }
685 // }
686 
687 /// Prints the identifier as a string that should be losslessly convertible
688 /// back into the same identifier.
689 impl fmt::Display for Ident {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result690     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
691         f.write_str(&self.to_string())
692     }
693 }
694 
695 impl fmt::Debug for Ident {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result696     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
697         f.debug_struct("Ident")
698             .field("ident", &self.to_string())
699             .field("span", &self.span())
700             .finish()
701     }
702 }
703 
704 /// A literal string (`"hello"`), byte string (`b"hello"`),
705 /// character (`'a'`), byte character (`b'a'`), an integer or floating point number
706 /// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
707 /// Boolean literals like `true` and `false` do not belong here, they are `Ident`s.
708 #[derive(Clone)]
709 pub struct Literal(bridge::client::Literal);
710 
711 macro_rules! suffixed_int_literals {
712     ($($name:ident => $kind:ident,)*) => ($(
713         /// Creates a new suffixed integer literal with the specified value.
714         ///
715         /// This function will create an integer like `1u32` where the integer
716         /// value specified is the first part of the token and the integral is
717         /// also suffixed at the end.
718         /// Literals created from negative numbers may not survive round-trips through
719         /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
720         ///
721         /// Literals created through this method have the `Span::call_site()`
722         /// span by default, which can be configured with the `set_span` method
723         /// below.
724         pub fn $name(n: $kind) -> Literal {
725             Literal(bridge::client::Literal::typed_integer(&n.to_string(), stringify!($kind)))
726         }
727     )*)
728 }
729 
730 macro_rules! unsuffixed_int_literals {
731     ($($name:ident => $kind:ident,)*) => ($(
732         /// Creates a new unsuffixed integer literal with the specified value.
733         ///
734         /// This function will create an integer like `1` where the integer
735         /// value specified is the first part of the token. No suffix is
736         /// specified on this token, meaning that invocations like
737         /// `Literal::i8_unsuffixed(1)` are equivalent to
738         /// `Literal::u32_unsuffixed(1)`.
739         /// Literals created from negative numbers may not survive rountrips through
740         /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
741         ///
742         /// Literals created through this method have the `Span::call_site()`
743         /// span by default, which can be configured with the `set_span` method
744         /// below.
745         pub fn $name(n: $kind) -> Literal {
746             Literal(bridge::client::Literal::integer(&n.to_string()))
747         }
748     )*)
749 }
750 
751 impl Literal {
752     suffixed_int_literals! {
753         u8_suffixed => u8,
754         u16_suffixed => u16,
755         u32_suffixed => u32,
756         u64_suffixed => u64,
757         u128_suffixed => u128,
758         usize_suffixed => usize,
759         i8_suffixed => i8,
760         i16_suffixed => i16,
761         i32_suffixed => i32,
762         i64_suffixed => i64,
763         i128_suffixed => i128,
764         isize_suffixed => isize,
765     }
766 
767     unsuffixed_int_literals! {
768         u8_unsuffixed => u8,
769         u16_unsuffixed => u16,
770         u32_unsuffixed => u32,
771         u64_unsuffixed => u64,
772         u128_unsuffixed => u128,
773         usize_unsuffixed => usize,
774         i8_unsuffixed => i8,
775         i16_unsuffixed => i16,
776         i32_unsuffixed => i32,
777         i64_unsuffixed => i64,
778         i128_unsuffixed => i128,
779         isize_unsuffixed => isize,
780     }
781 
782     /// Creates a new unsuffixed floating-point literal.
783     ///
784     /// This constructor is similar to those like `Literal::i8_unsuffixed` where
785     /// the float's value is emitted directly into the token but no suffix is
786     /// used, so it may be inferred to be a `f64` later in the compiler.
787     /// Literals created from negative numbers may not survive rountrips through
788     /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
789     ///
790     /// # Panics
791     ///
792     /// This function requires that the specified float is finite, for
793     /// example if it is infinity or NaN this function will panic.
f32_unsuffixed(n: f32) -> Literal794     pub fn f32_unsuffixed(n: f32) -> Literal {
795         if !n.is_finite() {
796             panic!("Invalid float literal {}", n);
797         }
798         Literal(bridge::client::Literal::float(&n.to_string()))
799     }
800 
801     /// Creates a new suffixed floating-point literal.
802     ///
803     /// This constructor will create a literal like `1.0f32` where the value
804     /// specified is the preceding part of the token and `f32` is the suffix of
805     /// the token. This token will always be inferred to be an `f32` in the
806     /// compiler.
807     /// Literals created from negative numbers may not survive rountrips through
808     /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
809     ///
810     /// # Panics
811     ///
812     /// This function requires that the specified float is finite, for
813     /// example if it is infinity or NaN this function will panic.
f32_suffixed(n: f32) -> Literal814     pub fn f32_suffixed(n: f32) -> Literal {
815         if !n.is_finite() {
816             panic!("Invalid float literal {}", n);
817         }
818         Literal(bridge::client::Literal::f32(&n.to_string()))
819     }
820 
821     /// Creates a new unsuffixed floating-point literal.
822     ///
823     /// This constructor is similar to those like `Literal::i8_unsuffixed` where
824     /// the float's value is emitted directly into the token but no suffix is
825     /// used, so it may be inferred to be a `f64` later in the compiler.
826     /// Literals created from negative numbers may not survive rountrips through
827     /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
828     ///
829     /// # Panics
830     ///
831     /// This function requires that the specified float is finite, for
832     /// example if it is infinity or NaN this function will panic.
f64_unsuffixed(n: f64) -> Literal833     pub fn f64_unsuffixed(n: f64) -> Literal {
834         if !n.is_finite() {
835             panic!("Invalid float literal {}", n);
836         }
837         Literal(bridge::client::Literal::float(&n.to_string()))
838     }
839 
840     /// Creates a new suffixed floating-point literal.
841     ///
842     /// This constructor will create a literal like `1.0f64` where the value
843     /// specified is the preceding part of the token and `f64` is the suffix of
844     /// the token. This token will always be inferred to be an `f64` in the
845     /// compiler.
846     /// Literals created from negative numbers may not survive rountrips through
847     /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
848     ///
849     /// # Panics
850     ///
851     /// This function requires that the specified float is finite, for
852     /// example if it is infinity or NaN this function will panic.
f64_suffixed(n: f64) -> Literal853     pub fn f64_suffixed(n: f64) -> Literal {
854         if !n.is_finite() {
855             panic!("Invalid float literal {}", n);
856         }
857         Literal(bridge::client::Literal::f64(&n.to_string()))
858     }
859 
860     /// String literal.
string(string: &str) -> Literal861     pub fn string(string: &str) -> Literal {
862         Literal(bridge::client::Literal::string(string))
863     }
864 
865     /// Character literal.
character(ch: char) -> Literal866     pub fn character(ch: char) -> Literal {
867         Literal(bridge::client::Literal::character(ch))
868     }
869 
870     /// Byte string literal.
byte_string(bytes: &[u8]) -> Literal871     pub fn byte_string(bytes: &[u8]) -> Literal {
872         Literal(bridge::client::Literal::byte_string(bytes))
873     }
874 
875     /// Returns the span encompassing this literal.
span(&self) -> Span876     pub fn span(&self) -> Span {
877         Span(self.0.span())
878     }
879 
880     /// Configures the span associated for this literal.
set_span(&mut self, span: Span)881     pub fn set_span(&mut self, span: Span) {
882         self.0.set_span(span.0);
883     }
884 
885     /// Returns a `Span` that is a subset of `self.span()` containing only the
886     /// source bytes in range `range`. Returns `None` if the would-be trimmed
887     /// span is outside the bounds of `self`.
888     // FIXME(SergioBenitez): check that the byte range starts and ends at a
889     // UTF-8 boundary of the source. otherwise, it's likely that a panic will
890     // occur elsewhere when the source text is printed.
891     // FIXME(SergioBenitez): there is no way for the user to know what
892     // `self.span()` actually maps to, so this method can currently only be
893     // called blindly. For example, `to_string()` for the character 'c' returns
894     // "'\u{63}'"; there is no way for the user to know whether the source text
895     // was 'c' or whether it was '\u{63}'.
subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span>896     pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
897         // HACK(eddyb) something akin to `Option::cloned`, but for `Bound<&T>`.
898         fn cloned_bound<T: Clone>(bound: Bound<&T>) -> Bound<T> {
899             match bound {
900                 Bound::Included(x) => Bound::Included(x.clone()),
901                 Bound::Excluded(x) => Bound::Excluded(x.clone()),
902                 Bound::Unbounded => Bound::Unbounded,
903             }
904         }
905 
906         self.0.subspan(cloned_bound(range.start_bound()), cloned_bound(range.end_bound())).map(Span)
907     }
908 }
909 
910 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
911 // based on it (the reverse of the usual relationship between the two).
912 // impl ToString for Literal {
913 //     fn to_string(&self) -> String {
914 //         TokenStream::from(TokenTree::from(self.clone())).to_string()
915 //     }
916 // }
917 
918 /// Prints the literal as a string that should be losslessly convertible
919 /// back into the same literal (except for possible rounding for floating point literals).
920 impl fmt::Display for Literal {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result921     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
922         f.write_str(&self.to_string())
923     }
924 }
925 
926 impl fmt::Debug for Literal {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result927     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
928         // FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
929         self.0.fmt(f)
930     }
931 }
932 
933 impl FromStr for Literal {
934     type Err = LexError;
935 
from_str(src: &str) -> Result<Self, LexError>936     fn from_str(src: &str) -> Result<Self, LexError> {
937         match bridge::client::Literal::from_str(src) {
938             Ok(literal) => Ok(Literal(literal)),
939             Err(()) => Err(LexError::new()),
940         }
941     }
942 }
943 
944 pub mod tracked_env {
945     use std::env::{self, VarError};
946     use std::ffi::OsStr;
947 
948     /// Retrieve an environment variable and add it to build dependency info.
949     /// Build system executing the compiler will know that the variable was accessed during
950     /// compilation, and will be able to rerun the build when the value of that variable changes.
951     /// Besides the dependency tracking this function should be equivalent to `env::var` from the
952     /// standard library, except that the argument must be UTF-8.
var<K: AsRef<OsStr> + AsRef<str>>(key: K) -> Result<String, VarError>953     pub fn var<K: AsRef<OsStr> + AsRef<str>>(key: K) -> Result<String, VarError> {
954         use std::ops::Deref;
955 
956         let key: &str = key.as_ref();
957         let value = env::var(key);
958         super::bridge::client::FreeFunctions::track_env_var(
959             key,
960             value.as_ref().map(|t| t.deref()).ok(),
961         );
962         value
963     }
964 }
965