Skip to content

Commit f8f60d8

Browse files
committed
auto merge of #12998 : huonw/rust/log_syntax, r=alexcrichton
syntax: allow `trace_macros!` and `log_syntax!` in item position. Previously trace_macros!(true) fn main() {} would complain about `trace_macros` being an expression macro in item position. This is a pointless limitation, because the macro is purely compile-time, with no runtime effect. (And similarly for log_syntax.) This also changes the behaviour of `trace_macros!` very slightly, it used to be equivalent to macro_rules! trace_macros { (true $($_x: tt)*) => { true }; (false $($_x: tt)*) => { false } } I.e. you could invoke it with arbitrary trailing arguments, which were ignored. It is changed to accept only exactly `true` or `false` (with no trailing arguments) and expands to `()`.
2 parents 11d9483 + cda3334 commit f8f60d8

File tree

6 files changed

+92
-36
lines changed

6 files changed

+92
-36
lines changed

src/libsyntax/ext/base.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,31 @@ impl MacResult {
119119
pub fn raw_dummy_expr(sp: codemap::Span) -> @ast::Expr {
120120
@ast::Expr {
121121
id: ast::DUMMY_NODE_ID,
122-
node: ast::ExprTup(Vec::new()),
123-
span: sp
122+
node: ast::ExprLit(@codemap::respan(sp, ast::LitNil)),
123+
span: sp,
124124
}
125125
}
126126
pub fn dummy_expr(sp: codemap::Span) -> MacResult {
127127
MRExpr(MacResult::raw_dummy_expr(sp))
128128
}
129+
pub fn dummy_any(sp: codemap::Span) -> MacResult {
130+
MRAny(~DummyMacResult { sp: sp })
131+
}
132+
}
133+
struct DummyMacResult {
134+
sp: codemap::Span
135+
}
136+
impl AnyMacro for DummyMacResult {
137+
fn make_expr(&self) -> @ast::Expr {
138+
MacResult::raw_dummy_expr(self.sp)
139+
}
140+
fn make_items(&self) -> SmallVector<@ast::Item> {
141+
SmallVector::zero()
142+
}
143+
fn make_stmt(&self) -> @ast::Stmt {
144+
@codemap::respan(self.sp,
145+
ast::StmtExpr(MacResult::raw_dummy_expr(self.sp), ast::DUMMY_NODE_ID))
146+
}
129147
}
130148

131149
/// An enum representing the different kinds of syntax extensions.

src/libsyntax/ext/log_syntax.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@
1010

1111
use ast;
1212
use codemap;
13-
use ext::base::*;
1413
use ext::base;
1514
use print;
1615

17-
pub fn expand_syntax_ext(cx: &mut ExtCtxt,
16+
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
1817
sp: codemap::Span,
1918
tt: &[ast::TokenTree])
2019
-> base::MacResult {
@@ -23,13 +22,6 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt,
2322
println!("{}", print::pprust::tt_to_str(&ast::TTDelim(
2423
@tt.iter().map(|x| (*x).clone()).collect())));
2524

26-
//trivial expression
27-
MRExpr(@ast::Expr {
28-
id: ast::DUMMY_NODE_ID,
29-
node: ast::ExprLit(@codemap::Spanned {
30-
node: ast::LitNil,
31-
span: sp
32-
}),
33-
span: sp,
34-
})
25+
// any so that `log_syntax` can be invoked as an expression and item.
26+
base::MacResult::dummy_any(sp)
3527
}

src/libsyntax/ext/trace_macros.rs

+10-22
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,21 @@ use ast;
1212
use codemap::Span;
1313
use ext::base::ExtCtxt;
1414
use ext::base;
15-
use parse::lexer::{new_tt_reader, Reader};
16-
use parse::parser::Parser;
17-
use parse::token::keywords;
15+
use parse::token::{keywords, is_keyword};
1816

1917
pub fn expand_trace_macros(cx: &mut ExtCtxt,
2018
sp: Span,
2119
tt: &[ast::TokenTree])
2220
-> base::MacResult {
23-
let sess = cx.parse_sess();
24-
let cfg = cx.cfg();
25-
let tt_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic,
26-
None,
27-
tt.iter().map(|x| (*x).clone()).collect());
28-
let mut rust_parser = Parser(sess, cfg.clone(), tt_rdr.dup());
29-
30-
if rust_parser.is_keyword(keywords::True) {
31-
cx.set_trace_macros(true);
32-
} else if rust_parser.is_keyword(keywords::False) {
33-
cx.set_trace_macros(false);
34-
} else {
35-
cx.span_err(sp, "trace_macros! only accepts `true` or `false`");
36-
return base::MacResult::dummy_expr(sp);
21+
match tt {
22+
[ast::TTTok(_, ref tok)] if is_keyword(keywords::True, tok) => {
23+
cx.set_trace_macros(true);
24+
}
25+
[ast::TTTok(_, ref tok)] if is_keyword(keywords::False, tok) => {
26+
cx.set_trace_macros(false);
27+
}
28+
_ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
3729
}
3830

39-
rust_parser.bump();
40-
41-
let mut rust_parser = Parser(sess, cfg, tt_rdr.dup());
42-
let result = rust_parser.parse_expr();
43-
base::MRExpr(result)
31+
base::MacResult::dummy_any(sp)
4432
}

src/test/compile-fail/issue-11692.rs

-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,4 @@ fn main() {
1515

1616
concat!(test!());
1717
//~^ ERROR: macro undefined: 'test'
18-
//~^^ ERROR: expected a literal
1918
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2014 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+
// ignore-fast feature doesn't work
12+
#[feature(macro_rules, trace_macros)];
13+
14+
fn main() {
15+
trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
16+
trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false`
17+
trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false`
18+
trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false`
19+
trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false`
20+
trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false`
21+
22+
23+
// should be fine:
24+
macro_rules! expando {
25+
($x: ident) => { trace_macros!($x) }
26+
}
27+
28+
expando!(true);
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2014 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+
// ignore-fast feature doesn't work
12+
#[feature(trace_macros, log_syntax)];
13+
14+
// make sure these macros can be used as in the various places that
15+
// macros can occur.
16+
17+
// items
18+
trace_macros!(false)
19+
log_syntax!()
20+
21+
fn main() {
22+
23+
// statements
24+
trace_macros!(false);
25+
log_syntax!();
26+
27+
// expressions
28+
(trace_macros!(false),
29+
log_syntax!());
30+
}

0 commit comments

Comments
 (0)