From dc0797c0c99e7079170d0e09f82fc6f66b721932 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sun, 15 Feb 2015 23:49:55 +0100 Subject: [PATCH] Address the other cases of #22234; fix #22234. The other cases: `concat_idents!`, `log_syntax!`, and `trace_macros!`, (these macros, with `asm!`, are handled (eagerly) in feature_gate.rs). --- src/libsyntax/ext/concat_idents.rs | 9 +++++ src/libsyntax/ext/expand.rs | 21 +++++++++++ src/libsyntax/ext/log_syntax.rs | 8 +++++ src/libsyntax/ext/trace_macros.rs | 10 ++++++ src/libsyntax/feature_gate.rs | 38 ++++++++++++++++---- src/test/compile-fail/concat_idents-gate.rs | 19 ++++++++++ src/test/compile-fail/concat_idents-gate2.rs | 17 +++++++++ src/test/compile-fail/log-syntax-gate2.rs | 13 +++++++ src/test/compile-fail/trace_macros-gate.rs | 30 ++++++++++++++++ src/test/compile-fail/trace_macros-gate2.rs | 20 +++++++++++ src/test/compile-fail/trace_macros-gate3.rs | 20 +++++++++++ 11 files changed, 199 insertions(+), 6 deletions(-) create mode 100644 src/test/compile-fail/concat_idents-gate.rs create mode 100644 src/test/compile-fail/concat_idents-gate2.rs create mode 100644 src/test/compile-fail/log-syntax-gate2.rs create mode 100644 src/test/compile-fail/trace_macros-gate.rs create mode 100644 src/test/compile-fail/trace_macros-gate2.rs create mode 100644 src/test/compile-fail/trace_macros-gate3.rs diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index 364cacd735cc7..63a8bd9ddf1b3 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -12,12 +12,21 @@ use ast; use codemap::Span; use ext::base::*; use ext::base; +use feature_gate; use parse::token; use parse::token::{str_to_ident}; use ptr::P; pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { + if !cx.ecfg.enable_concat_idents() { + feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, + "concat_idents", + sp, + feature_gate::EXPLAIN_CONCAT_IDENTS); + return base::DummyResult::expr(sp); + } + let mut res_str = String::new(); for (i, e) in tts.iter().enumerate() { if i & 1 == 1 { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index e31c1a3274984..72dc717910bc1 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1436,6 +1436,27 @@ impl<'feat> ExpansionConfig<'feat> { _ => false, } } + + pub fn enable_log_syntax(&self) -> bool { + match self.features { + Some(&Features { allow_log_syntax: true, .. }) => true, + _ => false, + } + } + + pub fn enable_concat_idents(&self) -> bool { + match self.features { + Some(&Features { allow_concat_idents: true, .. }) => true, + _ => false, + } + } + + pub fn enable_trace_macros(&self) -> bool { + match self.features { + Some(&Features { allow_trace_macros: true, .. }) => true, + _ => false, + } + } } pub fn expand_crate<'feat>(parse_sess: &parse::ParseSess, diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs index 30301e3b8cc92..8173dd93f7468 100644 --- a/src/libsyntax/ext/log_syntax.rs +++ b/src/libsyntax/ext/log_syntax.rs @@ -11,12 +11,20 @@ use ast; use codemap; use ext::base; +use feature_gate; use print; pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box { + if !cx.ecfg.enable_log_syntax() { + feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, + "log_syntax", + sp, + feature_gate::EXPLAIN_LOG_SYNTAX); + return base::DummyResult::any(sp); + } cx.print_backtrace(); diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index 76f7b7b0d7b3b..3fcc6a8d69241 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -12,6 +12,7 @@ use ast; use codemap::Span; use ext::base::ExtCtxt; use ext::base; +use feature_gate; use parse::token::keywords; @@ -19,6 +20,15 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt, sp: Span, tt: &[ast::TokenTree]) -> Box { + if !cx.ecfg.enable_trace_macros() { + feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, + "trace_macros", + sp, + feature_gate::EXPLAIN_TRACE_MACROS); + return base::DummyResult::any(sp); + } + + match tt { [ast::TtToken(_, ref tok)] if tok.is_keyword(keywords::True) => { cx.set_trace_macros(true); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9d14f894a46fb..5e29f3a6b6985 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -158,6 +158,9 @@ pub struct Features { pub visible_private_types: bool, pub allow_quote: bool, pub allow_asm: bool, + pub allow_log_syntax: bool, + pub allow_concat_idents: bool, + pub allow_trace_macros: bool, pub old_orphan_check: bool, pub simd_ffi: bool, pub unmarked_api: bool, @@ -175,6 +178,9 @@ impl Features { visible_private_types: false, allow_quote: false, allow_asm: false, + allow_log_syntax: false, + allow_concat_idents: false, + allow_trace_macros: false, old_orphan_check: false, simd_ffi: false, unmarked_api: false, @@ -226,6 +232,15 @@ pub fn emit_feature_warn(diag: &SpanHandler, feature: &str, span: Span, explain: pub const EXPLAIN_ASM: &'static str = "inline assembly is not stable enough for use and is subject to change"; +pub const EXPLAIN_LOG_SYNTAX: &'static str = + "`log_syntax!` is not stable enough for use and is subject to change"; + +pub const EXPLAIN_CONCAT_IDENTS: &'static str = + "`concat_idents` is not stable enough for use and is subject to change"; + +pub const EXPLAIN_TRACE_MACROS: &'static str = + "`trace_macros` is not stable enough for use and is subject to change"; + struct MacroVisitor<'a> { context: &'a Context<'a> } @@ -235,23 +250,28 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> { let ast::MacInvocTT(ref path, _, _) = mac.node; let id = path.segments.last().unwrap().identifier; + // Issue 22234: If you add a new case here, make sure to also + // add code to catch the macro during or after expansion. + // + // We still keep this MacroVisitor (rather than *solely* + // relying on catching cases during or after expansion) to + // catch uses of these macros within conditionally-compiled + // code, e.g. `#[cfg]`-guarded functions. + if id == token::str_to_ident("asm") { self.context.gate_feature("asm", path.span, EXPLAIN_ASM); } else if id == token::str_to_ident("log_syntax") { - self.context.gate_feature("log_syntax", path.span, "`log_syntax!` is not \ - stable enough for use and is subject to change"); + self.context.gate_feature("log_syntax", path.span, EXPLAIN_LOG_SYNTAX); } else if id == token::str_to_ident("trace_macros") { - self.context.gate_feature("trace_macros", path.span, "`trace_macros` is not \ - stable enough for use and is subject to change"); + self.context.gate_feature("trace_macros", path.span, EXPLAIN_TRACE_MACROS); } else if id == token::str_to_ident("concat_idents") { - self.context.gate_feature("concat_idents", path.span, "`concat_idents` is not \ - stable enough for use and is subject to change"); + self.context.gate_feature("concat_idents", path.span, EXPLAIN_CONCAT_IDENTS); } } } @@ -594,12 +614,18 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C check(&mut cx, krate); + // FIXME (pnkfelix): Before adding the 99th entry below, change it + // to a single-pass (instead of N calls to `.has_feature`). + Features { unboxed_closures: cx.has_feature("unboxed_closures"), rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"), visible_private_types: cx.has_feature("visible_private_types"), allow_quote: cx.has_feature("quote"), allow_asm: cx.has_feature("asm"), + allow_log_syntax: cx.has_feature("log_syntax"), + allow_concat_idents: cx.has_feature("concat_idents"), + allow_trace_macros: cx.has_feature("trace_macros"), old_orphan_check: cx.has_feature("old_orphan_check"), simd_ffi: cx.has_feature("simd_ffi"), unmarked_api: cx.has_feature("unmarked_api"), diff --git a/src/test/compile-fail/concat_idents-gate.rs b/src/test/compile-fail/concat_idents-gate.rs new file mode 100644 index 0000000000000..f4d97445725cd --- /dev/null +++ b/src/test/compile-fail/concat_idents-gate.rs @@ -0,0 +1,19 @@ +// Copyright 2015 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. + +const XY_1: i32 = 10; + +fn main() { + const XY_2: i32 = 20; + let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable + let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable + assert_eq!(a, 10); + assert_eq!(b, 20); +} diff --git a/src/test/compile-fail/concat_idents-gate2.rs b/src/test/compile-fail/concat_idents-gate2.rs new file mode 100644 index 0000000000000..d8f8f803edcc8 --- /dev/null +++ b/src/test/compile-fail/concat_idents-gate2.rs @@ -0,0 +1,17 @@ +// Copyright 2015 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. + +const XY_1: i32 = 10; + +fn main() { + const XY_2: i32 = 20; + assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable + assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable +} diff --git a/src/test/compile-fail/log-syntax-gate2.rs b/src/test/compile-fail/log-syntax-gate2.rs new file mode 100644 index 0000000000000..bb19e97ab0fa8 --- /dev/null +++ b/src/test/compile-fail/log-syntax-gate2.rs @@ -0,0 +1,13 @@ +// Copyright 2012 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!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable +} diff --git a/src/test/compile-fail/trace_macros-gate.rs b/src/test/compile-fail/trace_macros-gate.rs new file mode 100644 index 0000000000000..6473bcece91b6 --- /dev/null +++ b/src/test/compile-fail/trace_macros-gate.rs @@ -0,0 +1,30 @@ +// Copyright 2015 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. + +// Test that the trace_macros feature gate is on. + +fn main() { + trace_macros!(); //~ ERROR `trace_macros` is not stable + trace_macros!(1); //~ ERROR `trace_macros` is not stable + trace_macros!(ident); //~ ERROR `trace_macros` is not stable + trace_macros!(for); //~ ERROR `trace_macros` is not stable + trace_macros!(true,); //~ ERROR `trace_macros` is not stable + trace_macros!(false 1); //~ ERROR `trace_macros` is not stable + + // Errors are signalled early for the above, before expansion. + // See trace_macros-gate2 and trace_macros-gate3. for examples + // of the below being caught. + + macro_rules! expando { + ($x: ident) => { trace_macros!($x) } + } + + expando!(true); +} diff --git a/src/test/compile-fail/trace_macros-gate2.rs b/src/test/compile-fail/trace_macros-gate2.rs new file mode 100644 index 0000000000000..71cc45e132d33 --- /dev/null +++ b/src/test/compile-fail/trace_macros-gate2.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +// Test that the trace_macros feature gate is on. + +fn main() { + // (Infrastructure does not attempt to detect uses in macro definitions.) + macro_rules! expando { + ($x: ident) => { trace_macros!($x) } + } + + expando!(true); //~ ERROR `trace_macros` is not stable +} diff --git a/src/test/compile-fail/trace_macros-gate3.rs b/src/test/compile-fail/trace_macros-gate3.rs new file mode 100644 index 0000000000000..66d03cf9d8046 --- /dev/null +++ b/src/test/compile-fail/trace_macros-gate3.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +// Test that the trace_macros feature gate is on. + +pub fn main() { + println!("arg: {}", trace_macros!()); //~ ERROR `trace_macros` is not stable + println!("arg: {}", trace_macros!(1)); //~ ERROR `trace_macros` is not stable + println!("arg: {}", trace_macros!(ident)); //~ ERROR `trace_macros` is not stable + println!("arg: {}", trace_macros!(for)); //~ ERROR `trace_macros` is not stable + println!("arg: {}", trace_macros!(true,)); //~ ERROR `trace_macros` is not stable + println!("arg: {}", trace_macros!(false 1)); //~ ERROR `trace_macros` is not stable +}