Hide the quote_*! macros when the feature gate is off
This makes it easier to experiment with improved quasiquoting as an ordinary plugin library. The list of quote macros in feature_gate.rs was already out of sync; this commit also prevents that problem in the future.
This commit is contained in:
parent
5d653c17a6
commit
fc1b908322
@ -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,
|
||||
|
@ -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(
|
||||
@ -464,6 +466,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,
|
||||
@ -472,7 +475,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
ecfg: ecfg,
|
||||
trace_mac: false,
|
||||
exported_macros: Vec::new(),
|
||||
syntax_env: initial_syntax_expander_table(),
|
||||
syntax_env: env,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
"<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 {
|
||||
"<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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
17
src/test/run-pass/non-built-in-quote.rs
Normal file
17
src/test/run-pass/non-built-in-quote.rs
Normal file
@ -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 <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.
|
||||
|
||||
#![feature(macro_rules)]
|
||||
|
||||
macro_rules! quote_tokens ( () => (()) )
|
||||
|
||||
pub fn main() {
|
||||
quote_tokens!();
|
||||
}
|
Loading…
Reference in New Issue
Block a user