Skip to content

Commit 020e4e4

Browse files
committed
Rollup merge of #22383 - pnkfelix:pass-features-along-during-expansion, r=huonw
Pass features along during expansion Use the set of passed features to detect uses of feature-gated macros without the corresponding feature enabled. Fix #22234. ---- Also, the framework this add (passing along a reference to the features in the expansion context) is a necessary precursor for landing a properly feature-gated desugaring-based overloaded-`box` and placement-`in` (#22181). ---- This is fixing a bug, but since there might be code out there that is unknowingly taking advantage of that bug, I feel obligated to mark this as a: [breaking-change]
2 parents 0e89228 + dc0797c commit 020e4e4

15 files changed

+265
-28
lines changed

src/librustc_driver/driver.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,10 @@ pub fn phase_2_configure_and_expand(sess: &Session,
471471
new_path.extend(env::split_paths(&_old_path));
472472
env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
473473
}
474+
let features = sess.features.borrow();
474475
let cfg = syntax::ext::expand::ExpansionConfig {
475476
crate_name: crate_name.to_string(),
476-
enable_quotes: sess.features.borrow().quote,
477+
features: Some(&features),
477478
recursion_limit: sess.recursion_limit.get(),
478479
};
479480
let ret = syntax::ext::expand::expand_crate(&sess.parse_sess,

src/libsyntax/ext/asm.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use codemap;
1818
use codemap::Span;
1919
use ext::base;
2020
use ext::base::*;
21+
use feature_gate;
2122
use parse::token::InternedString;
2223
use parse::token;
2324
use ptr::P;
@@ -48,6 +49,12 @@ static OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"];
4849

4950
pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
5051
-> Box<base::MacResult+'cx> {
52+
if !cx.ecfg.enable_asm() {
53+
feature_gate::emit_feature_err(
54+
&cx.parse_sess.span_diagnostic, "asm", sp, feature_gate::EXPLAIN_ASM);
55+
return DummyResult::expr(sp);
56+
}
57+
5158
let mut p = cx.new_parser_from_tts(tts);
5259
let mut asm = InternedString::new("");
5360
let mut asm_str_style = None;

src/libsyntax/ext/base.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,8 @@ impl BlockInfo {
439439

440440
/// The base map of methods for expanding syntax extension
441441
/// AST nodes into full ASTs
442-
fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
442+
fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
443+
-> SyntaxEnv {
443444
// utility function to simplify creating NormalTT syntax extensions
444445
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
445446
NormalTT(box f, None)
@@ -470,7 +471,7 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
470471
syntax_expanders.insert(intern("deriving"),
471472
Decorator(box ext::deriving::expand_deprecated_deriving));
472473

473-
if ecfg.enable_quotes {
474+
if ecfg.enable_quotes() {
474475
// Quasi-quoting expanders
475476
syntax_expanders.insert(intern("quote_tokens"),
476477
builtin_normal_expander(
@@ -541,7 +542,7 @@ pub struct ExtCtxt<'a> {
541542
pub parse_sess: &'a parse::ParseSess,
542543
pub cfg: ast::CrateConfig,
543544
pub backtrace: ExpnId,
544-
pub ecfg: expand::ExpansionConfig,
545+
pub ecfg: expand::ExpansionConfig<'a>,
545546
pub use_std: bool,
546547

547548
pub mod_path: Vec<ast::Ident> ,
@@ -554,7 +555,7 @@ pub struct ExtCtxt<'a> {
554555

555556
impl<'a> ExtCtxt<'a> {
556557
pub fn new(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
557-
ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> {
558+
ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> {
558559
let env = initial_syntax_expander_table(&ecfg);
559560
ExtCtxt {
560561
parse_sess: parse_sess,

src/libsyntax/ext/concat_idents.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,21 @@ use ast;
1212
use codemap::Span;
1313
use ext::base::*;
1414
use ext::base;
15+
use feature_gate;
1516
use parse::token;
1617
use parse::token::{str_to_ident};
1718
use ptr::P;
1819

1920
pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
2021
-> Box<base::MacResult+'cx> {
22+
if !cx.ecfg.enable_concat_idents() {
23+
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
24+
"concat_idents",
25+
sp,
26+
feature_gate::EXPLAIN_CONCAT_IDENTS);
27+
return base::DummyResult::expr(sp);
28+
}
29+
2130
let mut res_str = String::new();
2231
for (i, e) in tts.iter().enumerate() {
2332
if i & 1 == 1 {

src/libsyntax/ext/expand.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use attr::AttrMetaMethods;
2222
use codemap;
2323
use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
2424
use ext::base::*;
25+
use feature_gate::{Features};
2526
use fold;
2627
use fold::*;
2728
use parse;
@@ -1408,28 +1409,63 @@ fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
14081409
}
14091410
}
14101411

1411-
pub struct ExpansionConfig {
1412+
pub struct ExpansionConfig<'feat> {
14121413
pub crate_name: String,
1413-
pub enable_quotes: bool,
1414+
pub features: Option<&'feat Features>,
14141415
pub recursion_limit: usize,
14151416
}
14161417

1417-
impl ExpansionConfig {
1418-
pub fn default(crate_name: String) -> ExpansionConfig {
1418+
impl<'feat> ExpansionConfig<'feat> {
1419+
pub fn default(crate_name: String) -> ExpansionConfig<'static> {
14191420
ExpansionConfig {
14201421
crate_name: crate_name,
1421-
enable_quotes: false,
1422+
features: None,
14221423
recursion_limit: 64,
14231424
}
14241425
}
1426+
1427+
pub fn enable_quotes(&self) -> bool {
1428+
match self.features {
1429+
Some(&Features { allow_quote: true, .. }) => true,
1430+
_ => false,
1431+
}
1432+
}
1433+
1434+
pub fn enable_asm(&self) -> bool {
1435+
match self.features {
1436+
Some(&Features { allow_asm: true, .. }) => true,
1437+
_ => false,
1438+
}
1439+
}
1440+
1441+
pub fn enable_log_syntax(&self) -> bool {
1442+
match self.features {
1443+
Some(&Features { allow_log_syntax: true, .. }) => true,
1444+
_ => false,
1445+
}
1446+
}
1447+
1448+
pub fn enable_concat_idents(&self) -> bool {
1449+
match self.features {
1450+
Some(&Features { allow_concat_idents: true, .. }) => true,
1451+
_ => false,
1452+
}
1453+
}
1454+
1455+
pub fn enable_trace_macros(&self) -> bool {
1456+
match self.features {
1457+
Some(&Features { allow_trace_macros: true, .. }) => true,
1458+
_ => false,
1459+
}
1460+
}
14251461
}
14261462

1427-
pub fn expand_crate(parse_sess: &parse::ParseSess,
1428-
cfg: ExpansionConfig,
1429-
// these are the macros being imported to this crate:
1430-
imported_macros: Vec<ast::MacroDef>,
1431-
user_exts: Vec<NamedSyntaxExtension>,
1432-
c: Crate) -> Crate {
1463+
pub fn expand_crate<'feat>(parse_sess: &parse::ParseSess,
1464+
cfg: ExpansionConfig<'feat>,
1465+
// these are the macros being imported to this crate:
1466+
imported_macros: Vec<ast::MacroDef>,
1467+
user_exts: Vec<NamedSyntaxExtension>,
1468+
c: Crate) -> Crate {
14331469
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
14341470
cx.use_std = std_inject::use_std(&c);
14351471

@@ -1598,7 +1634,7 @@ mod test {
15981634
// these following tests are quite fragile, in that they don't test what
15991635
// *kind* of failure occurs.
16001636

1601-
fn test_ecfg() -> ExpansionConfig {
1637+
fn test_ecfg() -> ExpansionConfig<'static> {
16021638
ExpansionConfig::default("test".to_string())
16031639
}
16041640

src/libsyntax/ext/log_syntax.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,20 @@
1111
use ast;
1212
use codemap;
1313
use ext::base;
14+
use feature_gate;
1415
use print;
1516

1617
pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt,
1718
sp: codemap::Span,
1819
tts: &[ast::TokenTree])
1920
-> Box<base::MacResult+'cx> {
21+
if !cx.ecfg.enable_log_syntax() {
22+
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
23+
"log_syntax",
24+
sp,
25+
feature_gate::EXPLAIN_LOG_SYNTAX);
26+
return base::DummyResult::any(sp);
27+
}
2028

2129
cx.print_backtrace();
2230

src/libsyntax/ext/trace_macros.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,23 @@ use ast;
1212
use codemap::Span;
1313
use ext::base::ExtCtxt;
1414
use ext::base;
15+
use feature_gate;
1516
use parse::token::keywords;
1617

1718

1819
pub fn expand_trace_macros(cx: &mut ExtCtxt,
1920
sp: Span,
2021
tt: &[ast::TokenTree])
2122
-> Box<base::MacResult+'static> {
23+
if !cx.ecfg.enable_trace_macros() {
24+
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
25+
"trace_macros",
26+
sp,
27+
feature_gate::EXPLAIN_TRACE_MACROS);
28+
return base::DummyResult::any(sp);
29+
}
30+
31+
2232
match tt {
2333
[ast::TtToken(_, ref tok)] if tok.is_keyword(keywords::True) => {
2434
cx.set_trace_macros(true);

src/libsyntax/feature_gate.rs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,11 @@ pub struct Features {
295295
pub unboxed_closures: bool,
296296
pub rustc_diagnostic_macros: bool,
297297
pub visible_private_types: bool,
298-
pub quote: bool,
298+
pub allow_quote: bool,
299+
pub allow_asm: bool,
300+
pub allow_log_syntax: bool,
301+
pub allow_concat_idents: bool,
302+
pub allow_trace_macros: bool,
299303
pub old_orphan_check: bool,
300304
pub simd_ffi: bool,
301305
pub unmarked_api: bool,
@@ -311,7 +315,11 @@ impl Features {
311315
unboxed_closures: false,
312316
rustc_diagnostic_macros: false,
313317
visible_private_types: false,
314-
quote: false,
318+
allow_quote: false,
319+
allow_asm: false,
320+
allow_log_syntax: false,
321+
allow_concat_idents: false,
322+
allow_trace_macros: false,
315323
old_orphan_check: false,
316324
simd_ffi: false,
317325
unmarked_api: false,
@@ -360,6 +368,18 @@ pub fn emit_feature_warn(diag: &SpanHandler, feature: &str, span: Span, explain:
360368
}
361369
}
362370

371+
pub const EXPLAIN_ASM: &'static str =
372+
"inline assembly is not stable enough for use and is subject to change";
373+
374+
pub const EXPLAIN_LOG_SYNTAX: &'static str =
375+
"`log_syntax!` is not stable enough for use and is subject to change";
376+
377+
pub const EXPLAIN_CONCAT_IDENTS: &'static str =
378+
"`concat_idents` is not stable enough for use and is subject to change";
379+
380+
pub const EXPLAIN_TRACE_MACROS: &'static str =
381+
"`trace_macros` is not stable enough for use and is subject to change";
382+
363383
struct MacroVisitor<'a> {
364384
context: &'a Context<'a>
365385
}
@@ -369,24 +389,28 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
369389
let ast::MacInvocTT(ref path, _, _) = mac.node;
370390
let id = path.segments.last().unwrap().identifier;
371391

392+
// Issue 22234: If you add a new case here, make sure to also
393+
// add code to catch the macro during or after expansion.
394+
//
395+
// We still keep this MacroVisitor (rather than *solely*
396+
// relying on catching cases during or after expansion) to
397+
// catch uses of these macros within conditionally-compiled
398+
// code, e.g. `#[cfg]`-guarded functions.
399+
372400
if id == token::str_to_ident("asm") {
373-
self.context.gate_feature("asm", path.span, "inline assembly is not \
374-
stable enough for use and is subject to change");
401+
self.context.gate_feature("asm", path.span, EXPLAIN_ASM);
375402
}
376403

377404
else if id == token::str_to_ident("log_syntax") {
378-
self.context.gate_feature("log_syntax", path.span, "`log_syntax!` is not \
379-
stable enough for use and is subject to change");
405+
self.context.gate_feature("log_syntax", path.span, EXPLAIN_LOG_SYNTAX);
380406
}
381407

382408
else if id == token::str_to_ident("trace_macros") {
383-
self.context.gate_feature("trace_macros", path.span, "`trace_macros` is not \
384-
stable enough for use and is subject to change");
409+
self.context.gate_feature("trace_macros", path.span, EXPLAIN_TRACE_MACROS);
385410
}
386411

387412
else if id == token::str_to_ident("concat_idents") {
388-
self.context.gate_feature("concat_idents", path.span, "`concat_idents` is not \
389-
stable enough for use and is subject to change");
413+
self.context.gate_feature("concat_idents", path.span, EXPLAIN_CONCAT_IDENTS);
390414
}
391415
}
392416
}
@@ -710,11 +734,18 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
710734

711735
check(&mut cx, krate);
712736

737+
// FIXME (pnkfelix): Before adding the 99th entry below, change it
738+
// to a single-pass (instead of N calls to `.has_feature`).
739+
713740
Features {
714741
unboxed_closures: cx.has_feature("unboxed_closures"),
715742
rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"),
716743
visible_private_types: cx.has_feature("visible_private_types"),
717-
quote: cx.has_feature("quote"),
744+
allow_quote: cx.has_feature("quote"),
745+
allow_asm: cx.has_feature("asm"),
746+
allow_log_syntax: cx.has_feature("log_syntax"),
747+
allow_concat_idents: cx.has_feature("concat_idents"),
748+
allow_trace_macros: cx.has_feature("trace_macros"),
718749
old_orphan_check: cx.has_feature("old_orphan_check"),
719750
simd_ffi: cx.has_feature("simd_ffi"),
720751
unmarked_api: cx.has_feature("unmarked_api"),

src/test/compile-fail/asm-gated2.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
unsafe {
13+
println!("{}", asm!("")); //~ ERROR inline assembly is not stable
14+
}
15+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
const XY_1: i32 = 10;
12+
13+
fn main() {
14+
const XY_2: i32 = 20;
15+
let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable
16+
let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable
17+
assert_eq!(a, 10);
18+
assert_eq!(b, 20);
19+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
const XY_1: i32 = 10;
12+
13+
fn main() {
14+
const XY_2: i32 = 20;
15+
assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable
16+
assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
13+
}

0 commit comments

Comments
 (0)