about summary refs log tree commit diff
path: root/src/libproc_macro
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-05-14 00:01:56 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-05-15 23:54:08 +0300
commitc1061254317ac747d2bf5901329545f4cec5ebcb (patch)
tree4abe39c1bf4c5db072c168ce019c195763e0920b /src/libproc_macro
parent5b820a694c0fd8392092c3f0301537aafe92cce2 (diff)
downloadrust-c1061254317ac747d2bf5901329545f4cec5ebcb.tar.gz
rust-c1061254317ac747d2bf5901329545f4cec5ebcb.zip
Represent lifetimes as two joint tokens in proc macros
Diffstat (limited to 'src/libproc_macro')
-rw-r--r--src/libproc_macro/lib.rs34
1 files changed, 18 insertions, 16 deletions
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index bf99a14a454..267922bf4a1 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -487,7 +487,7 @@ impl PartialEq<FileName> for SourceFile {
 pub enum TokenTree {
     /// A token stream surrounded by bracket delimiters.
     Group(Group),
-    /// An identifier or lifetime identifier.
+    /// An identifier.
     Ident(Ident),
     /// A single punctuation character (`+`, `,`, `$`, etc.).
     Punct(Punct),
@@ -702,9 +702,10 @@ impl !Sync for Punct {}
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "proc_macro", issue = "38356")]
 pub enum Spacing {
-    /// e.g. `+` is `Alone` in `+ =`, `+ident` or `+()`.
+    /// E.g. `+` is `Alone` in `+ =`, `+ident` or `+()`.
     Alone,
-    /// e.g. `+` is `Joint` in `+=` or `+#`.
+    /// E.g. `+` is `Joint` in `+=` or `'#`.
+    /// Additionally, single quote `'` can join with identifiers to form lifetimes `'ident`.
     Joint,
 }
 
@@ -717,8 +718,8 @@ impl Punct {
     /// which can be further configured with the `set_span` method below.
     #[unstable(feature = "proc_macro", issue = "38356")]
     pub fn new(ch: char, spacing: Spacing) -> Punct {
-        const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%',
-                                       '^', '&', '|', '@', '.', ',', ';', ':', '#', '$', '?'];
+        const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^',
+                                       '&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\''];
         if !LEGAL_CHARS.contains(&ch) {
             panic!("unsupported character `{:?}`", ch)
         }
@@ -766,7 +767,7 @@ impl fmt::Display for Punct {
     }
 }
 
-/// An identifier (`ident`) or lifetime identifier (`'ident`).
+/// An identifier (`ident`).
 #[derive(Clone, Debug)]
 #[unstable(feature = "proc_macro", issue = "38356")]
 pub struct Ident {
@@ -783,7 +784,7 @@ impl !Sync for Ident {}
 impl Ident {
     /// Creates a new `Ident` with the given `string` as well as the specified
     /// `span`.
-    /// The `string` argument must be a valid identifier or lifetime identifier permitted by the
+    /// The `string` argument must be a valid identifier permitted by the
     /// language, otherwise the function will panic.
     ///
     /// Note that `span`, currently in rustc, configures the hygiene information
@@ -817,8 +818,7 @@ impl Ident {
     pub fn new_raw(string: &str, span: Span) -> Ident {
         let mut ident = Ident::new(string, span);
         if ident.sym == keywords::Underscore.name() ||
-           token::is_path_segment_keyword(ast::Ident::with_empty_ctxt(ident.sym)) ||
-           ident.sym.as_str().starts_with("\'") {
+           token::is_path_segment_keyword(ast::Ident::with_empty_ctxt(ident.sym)) {
             panic!("`{:?}` is not a valid raw identifier", string)
         }
         ident.is_raw = true;
@@ -1211,13 +1211,19 @@ impl TokenTree {
             Pound => op!('#'),
             Dollar => op!('$'),
             Question => op!('?'),
+            SingleQuote => op!('\''),
 
-            Ident(ident, false) | Lifetime(ident) => {
+            Ident(ident, false) => {
                 tt!(self::Ident::new(&ident.name.as_str(), Span(span)))
             }
             Ident(ident, true) => {
                 tt!(self::Ident::new_raw(&ident.name.as_str(), Span(span)))
             }
+            Lifetime(ident) => {
+                let ident = ident.without_first_quote();
+                stack.push(tt!(self::Ident::new(&ident.name.as_str(), Span(span))));
+                tt!(Punct::new('\'', Spacing::Joint))
+            }
             Literal(lit, suffix) => tt!(self::Literal { lit, suffix, span: Span(span) }),
             DocComment(c) => {
                 let style = comments::doc_comment_style(&c.as_str());
@@ -1260,12 +1266,7 @@ impl TokenTree {
                 }).into();
             },
             self::TokenTree::Ident(tt) => {
-                let ident = ast::Ident::new(tt.sym, tt.span.0);
-                let token = if tt.sym.as_str().starts_with("'") {
-                    Lifetime(ident)
-                } else {
-                    Ident(ident, tt.is_raw)
-                };
+                let token = Ident(ast::Ident::new(tt.sym, tt.span.0), tt.is_raw);
                 return TokenTree::Token(tt.span.0, token).into();
             }
             self::TokenTree::Literal(self::Literal {
@@ -1324,6 +1325,7 @@ impl TokenTree {
             '#' => Pound,
             '$' => Dollar,
             '?' => Question,
+            '\'' => SingleQuote,
             _ => unreachable!(),
         };