Skip to content

Commit

Permalink
rustc: Fix procedural macros generating lifetime tokens
Browse files Browse the repository at this point in the history
This commit fixes an accidental regression from #50473 where lifetime tokens
produced by procedural macros ended up getting lost in translation in the
compiler and not actually producing parseable code. The issue lies in the fact
that a lifetime's `Ident` is prefixed with `'`. The `glue` implementation for
gluing joint tokens together forgot to take this into account so the lifetime
inside of `Ident` was missing the leading tick!

The `glue` implementation here is updated to create a new `Symbol` in these
situations to manufacture a new `Ident` with a leading tick to ensure it parses
correctly.

Closes #50942
  • Loading branch information
alexcrichton committed May 21, 2018
1 parent 6e6a4b1 commit 3b8f791
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/libsyntax/parse/token.rs
Expand Up @@ -22,6 +22,7 @@ use serialize::{Decodable, Decoder, Encodable, Encoder};
use symbol::keywords;
use syntax::parse::parse_stream_from_source_str;
use syntax_pos::{self, Span, FileName};
use syntax_pos::symbol::{self, Symbol};
use tokenstream::{TokenStream, TokenTree};
use tokenstream;

Expand Down Expand Up @@ -478,7 +479,13 @@ impl Token {
_ => return None,
},
SingleQuote => match joint {
Ident(ident, false) => Lifetime(ident),
Ident(ident, false) => {
let name = Symbol::intern(&format!("'{}", ident));
Lifetime(symbol::Ident {
name,
span: ident.span,
})
}
_ => return None,
},

Expand Down
@@ -0,0 +1,35 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// no-prefer-dynamic

#![crate_type = "proc-macro"]
#![feature(proc_macro)]

extern crate proc_macro;

use proc_macro::*;

#[proc_macro]
pub fn bar(_input: TokenStream) -> TokenStream {
let mut ret = Vec::<TokenTree>::new();
ret.push(Ident::new("static", Span::call_site()).into());
ret.push(Ident::new("FOO", Span::call_site()).into());
ret.push(Punct::new(':', Spacing::Alone).into());
ret.push(Punct::new('&', Spacing::Alone).into());
ret.push(Punct::new('\'', Spacing::Joint).into());
ret.push(Ident::new("static", Span::call_site()).into());
ret.push(Ident::new("i32", Span::call_site()).into());
ret.push(Punct::new('=', Spacing::Alone).into());
ret.push(Punct::new('&', Spacing::Alone).into());
ret.push(Literal::i32_unsuffixed(1).into());
ret.push(Punct::new(';', Spacing::Alone).into());
ret.into_iter().collect()
}
22 changes: 22 additions & 0 deletions src/test/run-pass-fulldeps/proc-macro/gen-lifetime-token.rs
@@ -0,0 +1,22 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:gen-lifetime-token.rs

#![feature(proc_macro)]

extern crate gen_lifetime_token as bar;

bar::bar!();

fn main() {
let x: &'static i32 = FOO;
assert_eq!(*x, 1);
}

0 comments on commit 3b8f791

Please sign in to comment.