From d8b34e9a74a4e91c4283ba4002a050ac0150cec6 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 29 Jan 2017 08:38:44 +0000 Subject: Add `syntax::ext::tt::quoted::{TokenTree, ..}` and remove `tokenstream::TokenTree::Sequence`. --- src/test/compile-fail-fulldeps/gated-quote.rs | 2 -- src/test/compile-fail/issue-35450.rs | 5 ++--- src/test/compile-fail/issue-39709.rs | 15 --------------- src/test/compile-fail/macro-error.rs | 2 +- src/test/compile-fail/macro-match-nonterminal.rs | 3 ++- src/test/compile-fail/macro-tt-matchers.rs | 13 +------------ src/test/compile-fail/malformed_macro_lhs.rs | 2 +- src/test/parse-fail/issue-33569.rs | 2 +- .../auxiliary/procedural_mbe_matching.rs | 4 +++- src/test/run-pass-fulldeps/mbe_matching_test_macro.rs | 4 ---- src/test/run-pass-fulldeps/quote-tokens.rs | 1 - src/test/run-pass/issue-39709.rs | 14 ++++++++++++++ 12 files changed, 25 insertions(+), 42 deletions(-) delete mode 100644 src/test/compile-fail/issue-39709.rs create mode 100644 src/test/run-pass/issue-39709.rs (limited to 'src/test') diff --git a/src/test/compile-fail-fulldeps/gated-quote.rs b/src/test/compile-fail-fulldeps/gated-quote.rs index 726af9864b4..63e1c6f16b3 100644 --- a/src/test/compile-fail-fulldeps/gated-quote.rs +++ b/src/test/compile-fail-fulldeps/gated-quote.rs @@ -54,8 +54,6 @@ pub fn main() { //~^ ERROR cannot find macro `quote_arm!` in this scope let x = quote_stmt!(ecx, 3); //~^ ERROR cannot find macro `quote_stmt!` in this scope - let x = quote_matcher!(ecx, 3); - //~^ ERROR cannot find macro `quote_matcher!` in this scope let x = quote_attr!(ecx, 3); //~^ ERROR cannot find macro `quote_attr!` in this scope let x = quote_arg!(ecx, 3); diff --git a/src/test/compile-fail/issue-35450.rs b/src/test/compile-fail/issue-35450.rs index d890d02a910..5f54f269c6c 100644 --- a/src/test/compile-fail/issue-35450.rs +++ b/src/test/compile-fail/issue-35450.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! m { ($t:tt) => { $t } } +macro_rules! m { ($($t:tt)*) => { $($t)* } } fn main() { - m!($t); //~ ERROR unknown macro variable - //~| ERROR expected expression + m!($t); //~ ERROR expected expression } diff --git a/src/test/compile-fail/issue-39709.rs b/src/test/compile-fail/issue-39709.rs deleted file mode 100644 index 0f66fe84393..00000000000 --- a/src/test/compile-fail/issue-39709.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2017 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - println!("{}", { macro_rules! x { ($()*) => {} } 33 }); - //~^ ERROR no syntax variables matched as repeating at this depth -} - diff --git a/src/test/compile-fail/macro-error.rs b/src/test/compile-fail/macro-error.rs index 78f95e365c4..82a5aa48729 100644 --- a/src/test/compile-fail/macro-error.rs +++ b/src/test/compile-fail/macro-error.rs @@ -9,7 +9,7 @@ // except according to those terms. macro_rules! foo { - ($a:expr) => $a; //~ ERROR macro rhs must be delimited + ($a:expr) => a; //~ ERROR macro rhs must be delimited } fn main() { diff --git a/src/test/compile-fail/macro-match-nonterminal.rs b/src/test/compile-fail/macro-match-nonterminal.rs index 6cca729e2c2..0af171b43fe 100644 --- a/src/test/compile-fail/macro-match-nonterminal.rs +++ b/src/test/compile-fail/macro-match-nonterminal.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! test { ($a, $b) => (()); } //~ ERROR missing fragment +macro_rules! test { ($a, //~ ERROR missing fragment + $b) => (()); } //~ ERROR missing fragment fn main() { test!() diff --git a/src/test/compile-fail/macro-tt-matchers.rs b/src/test/compile-fail/macro-tt-matchers.rs index 969f1500717..7255e7d00b6 100644 --- a/src/test/compile-fail/macro-tt-matchers.rs +++ b/src/test/compile-fail/macro-tt-matchers.rs @@ -17,16 +17,5 @@ macro_rules! foo { foo!(Box); -macro_rules! bar { - ($x:tt) => { - macro_rules! baz { - ($x:tt, $y:tt) => { ($x, $y) } - } - } -} - #[rustc_error] -fn main() { //~ ERROR compilation successful - bar!($y); - let _: (i8, i16) = baz!(0i8, 0i16); -} +fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/malformed_macro_lhs.rs b/src/test/compile-fail/malformed_macro_lhs.rs index 5d81e21f056..0b437be5393 100644 --- a/src/test/compile-fail/malformed_macro_lhs.rs +++ b/src/test/compile-fail/malformed_macro_lhs.rs @@ -9,7 +9,7 @@ // except according to those terms. macro_rules! my_precioooous { - $($t:tt)* => (1); //~ ERROR invalid macro matcher + t => (1); //~ ERROR invalid macro matcher } fn main() { diff --git a/src/test/parse-fail/issue-33569.rs b/src/test/parse-fail/issue-33569.rs index e3c17af82aa..d72bd8aab89 100644 --- a/src/test/parse-fail/issue-33569.rs +++ b/src/test/parse-fail/issue-33569.rs @@ -12,7 +12,7 @@ macro_rules! foo { { $+ } => { //~ ERROR expected identifier, found `+` + //~^ ERROR missing fragment specifier $(x)(y) //~ ERROR expected `*` or `+` - //~^ ERROR no rules expected the token `)` } } diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs index 2b3857048f3..3db69f2167c 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -23,6 +23,7 @@ use syntax::ast::{Ident, Pat}; use syntax::tokenstream::{TokenTree}; use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; use syntax::ext::build::AstBuilder; +use syntax::ext::tt::quoted; use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use syntax::ext::tt::macro_parser::{Success, Failure, Error}; use syntax::ext::tt::macro_parser::parse_failure_msg; @@ -33,7 +34,8 @@ use rustc_plugin::Registry; fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) -> Box { - let mbe_matcher = quote_matcher!(cx, $matched:expr, $($pat:pat)|+); + let mbe_matcher = quote_tokens!(cx, $$matched:expr, $$($$pat:pat)|+); + let mbe_matcher = quoted::parse(&mbe_matcher, true, cx.parse_sess); let map = match TokenTree::parse(cx, &mbe_matcher, args) { Success(map) => map, Failure(_, tok) => { diff --git a/src/test/run-pass-fulldeps/mbe_matching_test_macro.rs b/src/test/run-pass-fulldeps/mbe_matching_test_macro.rs index 5383b11cf53..822b2c9b93b 100644 --- a/src/test/run-pass-fulldeps/mbe_matching_test_macro.rs +++ b/src/test/run-pass-fulldeps/mbe_matching_test_macro.rs @@ -14,11 +14,7 @@ #![feature(plugin)] #![plugin(procedural_mbe_matching)] -#[no_link] -extern crate procedural_mbe_matching; - pub fn main() { - let abc = 123u32; assert_eq!(matches!(Some(123), None | Some(0)), false); assert_eq!(matches!(Some(123), None | Some(123)), true); assert_eq!(matches!(true, true), true); diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs index 9e9b7ce5bf2..8e6a69cb584 100644 --- a/src/test/run-pass-fulldeps/quote-tokens.rs +++ b/src/test/run-pass-fulldeps/quote-tokens.rs @@ -37,7 +37,6 @@ fn syntax_extension(cx: &ExtCtxt) { let _l: P = quote_ty!(cx, &isize); - let _m: Vec = quote_matcher!(cx, $($foo:tt,)* bar); let _n: syntax::ast::Attribute = quote_attr!(cx, #![cfg(foo, bar = "baz")]); let _o: Option> = quote_item!(cx, fn foo() {}); diff --git a/src/test/run-pass/issue-39709.rs b/src/test/run-pass/issue-39709.rs new file mode 100644 index 00000000000..ebca9312a64 --- /dev/null +++ b/src/test/run-pass/issue-39709.rs @@ -0,0 +1,14 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + println!("{}", { macro_rules! x { ($(t:tt)*) => {} } 33 }); +} + -- cgit 1.4.1-3-g733a5 From 61a9a14d29529dee188d76dbf5c9faaefa9fce87 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 26 Feb 2017 03:25:22 +0000 Subject: Add warning cycle. --- src/librustc/lint/builtin.rs | 7 ++++++ src/librustc_driver/driver.rs | 8 ++++++ src/librustc_lint/lib.rs | 4 +++ src/libsyntax/ext/tt/macro_parser.rs | 32 +++++++++++++++++------- src/libsyntax/ext/tt/macro_rules.rs | 3 ++- src/libsyntax/ext/tt/quoted.rs | 3 ++- src/libsyntax/parse/lexer/mod.rs | 2 ++ src/libsyntax/parse/mod.rs | 2 ++ src/test/compile-fail/issue-39404.rs | 18 +++++++++++++ src/test/compile-fail/macro-match-nonterminal.rs | 3 +-- src/test/parse-fail/issue-33569.rs | 2 ++ 11 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 src/test/compile-fail/issue-39404.rs (limited to 'src/test') diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 70f03e02f46..b2f508ff26d 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -236,6 +236,12 @@ declare_lint! { "detects use of struct constructors that would be invisible with new visibility rules" } +declare_lint! { + pub MISSING_FRAGMENT_SPECIFIER, + Warn, + "detects missing fragment specifiers in unused `macro_rules!` patterns" +} + declare_lint! { pub DEPRECATED, Warn, @@ -286,6 +292,7 @@ impl LintPass for HardwiredLints { LEGACY_DIRECTORY_OWNERSHIP, LEGACY_IMPORTS, LEGACY_CONSTRUCTOR_VISIBILITY, + MISSING_FRAGMENT_SPECIFIER, DEPRECATED ) } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index ddf09f5cfe0..9619ba84724 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -688,6 +688,14 @@ pub fn phase_2_configure_and_expand(sess: &Session, let krate = ecx.monotonic_expander().expand_crate(krate); + let mut missing_fragment_specifiers: Vec<_> = + ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect(); + missing_fragment_specifiers.sort(); + for span in missing_fragment_specifiers { + let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; + let msg = "missing fragment specifier".to_string(); + sess.add_lint(lint, ast::CRATE_NODE_ID, span, msg); + } if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count { ecx.parse_sess.span_diagnostic.abort_if_errors(); } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 8fb1740e66e..b87edf54823 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -247,6 +247,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY), reference: "issue #39207 ", }, + FutureIncompatibleInfo { + id: LintId::of(MISSING_FRAGMENT_SPECIFIER), + reference: "issue #40107 ", + }, ]); // Register renamed and removed lints diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index a466fd2c6db..6ab5123bc87 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -87,6 +87,7 @@ use parse::{Directory, ParseSess}; use parse::parser::{PathStyle, Parser}; use parse::token::{self, DocComment, Token, Nonterminal}; use print::pprust; +use symbol::keywords; use tokenstream::TokenTree; use util::small_vector::SmallVector; @@ -201,22 +202,27 @@ pub enum NamedMatch { MatchedNonterminal(Rc) } -fn nameize>>(ms: &[quoted::TokenTree], mut res: I) +fn nameize>>(sess: &ParseSess, ms: &[quoted::TokenTree], mut res: I) -> NamedParseResult { use self::quoted::TokenTree; - fn n_rec>>(m: &TokenTree, mut res: &mut I, + fn n_rec>>(sess: &ParseSess, m: &TokenTree, mut res: &mut I, ret_val: &mut HashMap>) -> Result<(), (syntax_pos::Span, String)> { match *m { TokenTree::Sequence(_, ref seq) => { for next_m in &seq.tts { - n_rec(next_m, res.by_ref(), ret_val)? + n_rec(sess, next_m, res.by_ref(), ret_val)? } } TokenTree::Delimited(_, ref delim) => { for next_m in &delim.tts { - n_rec(next_m, res.by_ref(), ret_val)?; + n_rec(sess, next_m, res.by_ref(), ret_val)?; + } + } + TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => { + if sess.missing_fragment_specifiers.borrow_mut().remove(&span) { + return Err((span, "missing fragment specifier".to_string())); } } TokenTree::MetaVarDecl(sp, bind_name, _) => { @@ -237,7 +243,7 @@ fn nameize>>(ms: &[quoted::TokenTree], mut res: let mut ret_val = HashMap::new(); for m in ms { - match n_rec(m, res.by_ref(), &mut ret_val) { + match n_rec(sess, m, res.by_ref(), &mut ret_val) { Ok(_) => {}, Err((sp, msg)) => return Error(sp, msg), } @@ -277,11 +283,13 @@ fn create_matches(len: usize) -> Vec>> { (0..len).into_iter().map(|_| Vec::new()).collect() } -fn inner_parse_loop(cur_eis: &mut SmallVector>, +fn inner_parse_loop(sess: &ParseSess, + cur_eis: &mut SmallVector>, next_eis: &mut Vec>, eof_eis: &mut SmallVector>, bb_eis: &mut SmallVector>, - token: &Token, span: &syntax_pos::Span) -> ParseResult<()> { + token: &Token, + span: &syntax_pos::Span) -> ParseResult<()> { use self::quoted::TokenTree; while let Some(mut ei) = cur_eis.pop() { @@ -375,6 +383,11 @@ fn inner_parse_loop(cur_eis: &mut SmallVector>, top_elts: Tt(TokenTree::Sequence(sp, seq)), })); } + TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => { + if sess.missing_fragment_specifiers.borrow_mut().remove(&span) { + return Error(span, "missing fragment specifier".to_string()); + } + } TokenTree::MetaVarDecl(..) => { // Built-in nonterminals never start with these tokens, // so we can eliminate them from consideration. @@ -422,7 +435,7 @@ pub fn parse(sess: &ParseSess, let mut eof_eis = SmallVector::new(); assert!(next_eis.is_empty()); - match inner_parse_loop(&mut cur_eis, &mut next_eis, &mut eof_eis, &mut bb_eis, + match inner_parse_loop(sess, &mut cur_eis, &mut next_eis, &mut eof_eis, &mut bb_eis, &parser.token, &parser.span) { Success(_) => {}, Failure(sp, tok) => return Failure(sp, tok), @@ -435,7 +448,8 @@ pub fn parse(sess: &ParseSess, /* error messages here could be improved with links to orig. rules */ if token_name_eq(&parser.token, &token::Eof) { if eof_eis.len() == 1 { - return nameize(ms, eof_eis[0].matches.iter_mut().map(|mut dv| dv.pop().unwrap())); + let matches = eof_eis[0].matches.iter_mut().map(|mut dv| dv.pop().unwrap()); + return nameize(sess, ms, matches); } else if eof_eis.len() > 1 { return Error(parser.span, "ambiguity: multiple successful parses".to_string()); } else { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index c775b2325cd..193c06707c7 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -788,6 +788,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result Ok(true), // keywords::Invalid _ => Err((format!("invalid fragment specifier `{}`", frag), "valid fragment specifiers are `ident`, `block`, \ `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \ @@ -810,7 +811,7 @@ fn has_legal_fragment_specifier(tok: "ed::TokenTree) -> Result<(), String> { fn is_legal_fragment_specifier(frag: &str) -> bool { match frag { "item" | "block" | "stmt" | "expr" | "pat" | - "path" | "ty" | "ident" | "meta" | "tt" => true, + "path" | "ty" | "ident" | "meta" | "tt" | "" => true, _ => false, } } diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 4fc20d7fefa..530824b2834 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -143,7 +143,8 @@ pub fn parse(input: &[tokenstream::TokenTree], expect_matchers: bool, sess: &Par }, tree @ _ => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp), }; - sess.span_diagnostic.span_err(span, "missing fragment specifier"); + sess.missing_fragment_specifiers.borrow_mut().insert(span); + result.push(TokenTree::MetaVarDecl(span, ident, keywords::Invalid.ident())); } _ => result.push(tree), } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index b7f6e6a2384..de8a87e3a2b 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1693,6 +1693,7 @@ mod tests { use feature_gate::UnstableFeatures; use parse::token; use std::cell::RefCell; + use std::collections::HashSet; use std::io; use std::rc::Rc; @@ -1704,6 +1705,7 @@ mod tests { config: CrateConfig::new(), included_mod_stack: RefCell::new(Vec::new()), code_map: cm, + missing_fragment_specifiers: RefCell::new(HashSet::new()), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 78fd706b27a..6fec49b229a 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -46,6 +46,7 @@ pub struct ParseSess { pub span_diagnostic: Handler, pub unstable_features: UnstableFeatures, pub config: CrateConfig, + pub missing_fragment_specifiers: RefCell>, /// Used to determine and report recursive mod inclusions included_mod_stack: RefCell>, code_map: Rc, @@ -66,6 +67,7 @@ impl ParseSess { span_diagnostic: handler, unstable_features: UnstableFeatures::from_environment(), config: HashSet::new(), + missing_fragment_specifiers: RefCell::new(HashSet::new()), included_mod_stack: RefCell::new(vec![]), code_map: code_map } diff --git a/src/test/compile-fail/issue-39404.rs b/src/test/compile-fail/issue-39404.rs new file mode 100644 index 00000000000..0168ae7d910 --- /dev/null +++ b/src/test/compile-fail/issue-39404.rs @@ -0,0 +1,18 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(missing_fragment_specifier)] //~ NOTE lint level defined here + +macro_rules! m { ($i) => {} } +//~^ ERROR missing fragment specifier +//~| WARN previously accepted +//~| NOTE issue #40107 + +fn main() {} diff --git a/src/test/compile-fail/macro-match-nonterminal.rs b/src/test/compile-fail/macro-match-nonterminal.rs index 0af171b43fe..6cca729e2c2 100644 --- a/src/test/compile-fail/macro-match-nonterminal.rs +++ b/src/test/compile-fail/macro-match-nonterminal.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! test { ($a, //~ ERROR missing fragment - $b) => (()); } //~ ERROR missing fragment +macro_rules! test { ($a, $b) => (()); } //~ ERROR missing fragment fn main() { test!() diff --git a/src/test/parse-fail/issue-33569.rs b/src/test/parse-fail/issue-33569.rs index d72bd8aab89..15d491719a6 100644 --- a/src/test/parse-fail/issue-33569.rs +++ b/src/test/parse-fail/issue-33569.rs @@ -16,3 +16,5 @@ macro_rules! foo { $(x)(y) //~ ERROR expected `*` or `+` } } + +foo!(); -- cgit 1.4.1-3-g733a5 From 839398a0b4a5b77fe3dd351107b1cbe45e1004de Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 28 Feb 2017 03:07:23 +0000 Subject: Add regression test. --- .../proc-macro/auxiliary/issue-39889.rs | 27 ++++++++++++++++++++++ .../run-pass-fulldeps/proc-macro/issue-39889.rs | 22 ++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-39889.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/issue-39889.rs (limited to 'src/test') diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-39889.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-39889.rs new file mode 100644 index 00000000000..9094310fb3e --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-39889.rs @@ -0,0 +1,27 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(Issue39889)] +pub fn f(_input: TokenStream) -> TokenStream { + let rules = r#" + macro_rules! id { + ($($tt:tt)*) => { $($tt)* }; + } + "#; + rules.parse().unwrap() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-39889.rs b/src/test/run-pass-fulldeps/proc-macro/issue-39889.rs new file mode 100644 index 00000000000..05610116ad6 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/issue-39889.rs @@ -0,0 +1,22 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue-39889.rs + +#![feature(proc_macro)] +#![allow(unused)] + +extern crate issue_39889; +use issue_39889::Issue39889; + +#[derive(Issue39889)] +struct S; + +fn main() {} -- cgit 1.4.1-3-g733a5