diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 80e507b7a79..3a4b05ba00a 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -288,8 +288,9 @@ pub fn phase_2_configure_and_expand(sess: &Session, os::setenv("PATH", os::join_paths(new_path.as_slice()).unwrap()); } let cfg = syntax::ext::expand::ExpansionConfig { - deriving_hash_type_parameter: sess.features.borrow().default_type_params, crate_name: crate_name.to_string(), + deriving_hash_type_parameter: sess.features.borrow().default_type_params, + enable_quotes: sess.features.borrow().quote, }; let ret = syntax::ext::expand::expand_crate(&sess.parse_sess, cfg, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 8bf13e20fed..212cd33e16e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -344,7 +344,7 @@ impl BlockInfo { /// The base map of methods for expanding syntax extension /// AST nodes into full ASTs -fn initial_syntax_expander_table() -> SyntaxEnv { +fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv { // utility function to simplify creating NormalTT syntax extensions fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension { NormalTT(box f, None) @@ -383,31 +383,33 @@ fn initial_syntax_expander_table() -> SyntaxEnv { syntax_expanders.insert(intern("deriving"), Decorator(box ext::deriving::expand_meta_deriving)); - // Quasi-quoting expanders - syntax_expanders.insert(intern("quote_tokens"), - builtin_normal_expander( - ext::quote::expand_quote_tokens)); - syntax_expanders.insert(intern("quote_expr"), - builtin_normal_expander( - ext::quote::expand_quote_expr)); - syntax_expanders.insert(intern("quote_ty"), - builtin_normal_expander( - ext::quote::expand_quote_ty)); - syntax_expanders.insert(intern("quote_method"), - builtin_normal_expander( - ext::quote::expand_quote_method)); - syntax_expanders.insert(intern("quote_item"), - builtin_normal_expander( - ext::quote::expand_quote_item)); - syntax_expanders.insert(intern("quote_pat"), - builtin_normal_expander( - ext::quote::expand_quote_pat)); - syntax_expanders.insert(intern("quote_arm"), - builtin_normal_expander( - ext::quote::expand_quote_arm)); - syntax_expanders.insert(intern("quote_stmt"), - builtin_normal_expander( - ext::quote::expand_quote_stmt)); + if ecfg.enable_quotes { + // Quasi-quoting expanders + syntax_expanders.insert(intern("quote_tokens"), + builtin_normal_expander( + ext::quote::expand_quote_tokens)); + syntax_expanders.insert(intern("quote_expr"), + builtin_normal_expander( + ext::quote::expand_quote_expr)); + syntax_expanders.insert(intern("quote_ty"), + builtin_normal_expander( + ext::quote::expand_quote_ty)); + syntax_expanders.insert(intern("quote_method"), + builtin_normal_expander( + ext::quote::expand_quote_method)); + syntax_expanders.insert(intern("quote_item"), + builtin_normal_expander( + ext::quote::expand_quote_item)); + syntax_expanders.insert(intern("quote_pat"), + builtin_normal_expander( + ext::quote::expand_quote_pat)); + syntax_expanders.insert(intern("quote_arm"), + builtin_normal_expander( + ext::quote::expand_quote_arm)); + syntax_expanders.insert(intern("quote_stmt"), + builtin_normal_expander( + ext::quote::expand_quote_stmt)); + } syntax_expanders.insert(intern("line"), builtin_normal_expander( @@ -466,6 +468,7 @@ pub struct ExtCtxt<'a> { impl<'a> ExtCtxt<'a> { pub fn new<'a>(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig, ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> { + let env = initial_syntax_expander_table(&ecfg); ExtCtxt { parse_sess: parse_sess, cfg: cfg, @@ -474,7 +477,7 @@ impl<'a> ExtCtxt<'a> { ecfg: ecfg, trace_mac: false, exported_macros: Vec::new(), - syntax_env: initial_syntax_expander_table(), + syntax_env: env, } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 70cf41d5e17..9f3df1a7623 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -975,8 +975,19 @@ fn new_span(cx: &ExtCtxt, sp: Span) -> Span { } pub struct ExpansionConfig { - pub deriving_hash_type_parameter: bool, pub crate_name: String, + pub deriving_hash_type_parameter: bool, + pub enable_quotes: bool, +} + +impl ExpansionConfig { + pub fn default(crate_name: String) -> ExpansionConfig { + ExpansionConfig { + crate_name: crate_name, + deriving_hash_type_parameter: false, + enable_quotes: false, + } + } } pub struct ExportedMacros { @@ -1106,7 +1117,7 @@ impl<'a, 'v> Visitor<'v> for MacroExterminator<'a> { #[cfg(test)] mod test { use super::{pattern_bindings, expand_crate, contains_macro_escape}; - use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer}; + use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer, ExpansionConfig}; use ast; use ast::{Attribute_, AttrOuter, MetaWord, Name}; use attr; @@ -1171,6 +1182,10 @@ mod test { // these following tests are quite fragile, in that they don't test what // *kind* of failure occurs. + fn test_ecfg() -> ExpansionConfig { + ExpansionConfig::default("test".to_string()) + } + // make sure that macros can't escape fns #[should_fail] #[test] fn macros_cant_escape_fns_test () { @@ -1182,11 +1197,7 @@ mod test { src, Vec::new(), &sess); // should fail: - let cfg = ::syntax::ext::expand::ExpansionConfig { - deriving_hash_type_parameter: false, - crate_name: "test".to_string(), - }; - expand_crate(&sess,cfg,vec!(),vec!(),crate_ast); + expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast); } // make sure that macros can't escape modules @@ -1199,11 +1210,7 @@ mod test { "".to_string(), src, Vec::new(), &sess); - let cfg = ::syntax::ext::expand::ExpansionConfig { - deriving_hash_type_parameter: false, - crate_name: "test".to_string(), - }; - expand_crate(&sess,cfg,vec!(),vec!(),crate_ast); + expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast); } // macro_escape modules should allow macros to escape @@ -1215,11 +1222,7 @@ mod test { "".to_string(), src, Vec::new(), &sess); - let cfg = ::syntax::ext::expand::ExpansionConfig { - deriving_hash_type_parameter: false, - crate_name: "test".to_string(), - }; - expand_crate(&sess, cfg, vec!(), vec!(), crate_ast); + expand_crate(&sess, test_ecfg(), vec!(), vec!(), crate_ast); } #[test] fn test_contains_flatten (){ @@ -1252,11 +1255,7 @@ mod test { let ps = parse::new_parse_sess(); let crate_ast = string_to_parser(&ps, crate_str).parse_crate_mod(); // the cfg argument actually does matter, here... - let cfg = ::syntax::ext::expand::ExpansionConfig { - deriving_hash_type_parameter: false, - crate_name: "test".to_string(), - }; - expand_crate(&ps,cfg,vec!(),vec!(),crate_ast) + expand_crate(&ps,test_ecfg(),vec!(),vec!(),crate_ast) } // find the pat_ident paths in a crate diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index cd0fa184a09..1c6ee8acc94 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -102,6 +102,7 @@ pub struct Features { pub rustc_diagnostic_macros: bool, pub import_shadowing: bool, pub visible_private_types: bool, + pub quote: bool, } impl Features { @@ -112,6 +113,7 @@ impl Features { rustc_diagnostic_macros: false, import_shadowing: false, visible_private_types: false, + quote: false, } } } @@ -282,10 +284,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { fn visit_mac(&mut self, macro: &ast::Mac) { let ast::MacInvocTT(ref path, _, _) = macro.node; let id = path.segments.last().unwrap().identifier; - let quotes = ["quote_tokens", "quote_expr", "quote_ty", - "quote_item", "quote_pat", "quote_stmt"]; - let msg = " is not stable enough for use and are subject to change"; - if id == token::str_to_ident("macro_rules") { self.gate_feature("macro_rules", path.span, "macro definitions are \ @@ -311,16 +309,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { self.gate_feature("concat_idents", path.span, "`concat_idents` is not \ stable enough for use and is subject to change"); } - - else { - for "e in quotes.iter() { - if id == token::str_to_ident(quote) { - self.gate_feature("quote", - path.span, - format!("{}{}", quote, msg).as_slice()); - } - } - } } fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { @@ -483,6 +471,7 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"), import_shadowing: cx.has_feature("import_shadowing"), visible_private_types: cx.has_feature("visible_private_types"), + quote: cx.has_feature("quote"), }, unknown_features) } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 091b0ce8ed9..828a6124aa0 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -235,10 +235,7 @@ fn generate_test_harness(sess: &ParseSess, sess: sess, span_diagnostic: sd, ext_cx: ExtCtxt::new(sess, cfg.clone(), - ExpansionConfig { - deriving_hash_type_parameter: false, - crate_name: "test".to_string(), - }), + ExpansionConfig::default("test".to_string())), path: Vec::new(), testfns: Vec::new(), reexport_test_harness_main: reexport_test_harness_main, diff --git a/src/test/run-pass/non-built-in-quote.rs b/src/test/run-pass/non-built-in-quote.rs new file mode 100644 index 00000000000..c6dd3736857 --- /dev/null +++ b/src/test/run-pass/non-built-in-quote.rs @@ -0,0 +1,17 @@ +// Copyright 2014 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. + +#![feature(macro_rules)] + +macro_rules! quote_tokens ( () => (()) ) + +pub fn main() { + quote_tokens!(); +}