Skip to content

Commit f381a96

Browse files
committed
Auto merge of #56897 - euclio:parse-fatal, r=estebank
make `panictry!` private to libsyntax This commit completely removes usage of the `panictry!` macro from outside libsyntax. The macro causes parse errors to be fatal, so using it in libsyntax_ext caused parse failures *within* a syntax extension to be fatal, which is probably not intended. Furthermore, this commit adds spans to diagnostics emitted by empty extensions if they were missing, à la #56491.
2 parents d6d32ac + 0a6fb84 commit f381a96

22 files changed

+451
-134
lines changed

src/librustdoc/core.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use syntax::json::JsonEmitter;
2323
use syntax::ptr::P;
2424
use syntax::symbol::keywords;
2525
use syntax_pos::DUMMY_SP;
26-
use errors;
26+
use errors::{self, FatalError};
2727
use errors::emitter::{Emitter, EmitterWriter};
2828
use parking_lot::ReentrantMutex;
2929

@@ -429,7 +429,13 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
429429

430430
let control = &driver::CompileController::basic();
431431

432-
let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input));
432+
let krate = match driver::phase_1_parse_input(control, &sess, &input) {
433+
Ok(krate) => krate,
434+
Err(mut e) => {
435+
e.emit();
436+
FatalError.raise();
437+
}
438+
};
433439

434440
let name = match crate_name {
435441
Some(ref crate_name) => crate_name.clone(),

src/librustdoc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ extern crate rustc_metadata;
3232
extern crate rustc_target;
3333
extern crate rustc_typeck;
3434
extern crate serialize;
35-
#[macro_use] extern crate syntax;
35+
extern crate syntax;
3636
extern crate syntax_pos;
3737
extern crate test as testing;
3838
#[macro_use] extern crate log;

src/librustdoc/test.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use errors;
1+
use errors::{self, FatalError};
22
use errors::emitter::ColorConfig;
33
use rustc_data_structures::sync::Lrc;
44
use rustc_lint;
@@ -84,9 +84,14 @@ pub fn run(mut options: Options) -> isize {
8484
target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
8585
sess.parse_sess.config = cfg;
8686

87-
let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(),
88-
&sess,
89-
&input));
87+
let krate =
88+
match driver::phase_1_parse_input(&driver::CompileController::basic(), &sess, &input) {
89+
Ok(krate) => krate,
90+
Err(mut e) => {
91+
e.emit();
92+
FatalError.raise();
93+
}
94+
};
9095
let driver::ExpansionResult { defs, mut hir_forest, .. } = {
9196
phase_2_configure_and_expand(
9297
&sess,

src/libsyntax/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ use ast::AttrId;
4444
// way towards a non-panic!-prone parser. It should be used for fatal parsing
4545
// errors; eventually we plan to convert all code using panictry to just use
4646
// normal try.
47-
// Exported for syntax_ext, not meant for general use.
48-
#[macro_export]
4947
macro_rules! panictry {
5048
($e:expr) => ({
5149
use std::result::Result::{Ok, Err};

src/libsyntax_ext/asm.rs

+71-45
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use self::State::*;
44

55
use rustc_data_structures::thin_vec::ThinVec;
66

7+
use errors::DiagnosticBuilder;
78
use syntax::ast;
89
use syntax::ext::base;
910
use syntax::ext::base::*;
@@ -51,6 +52,34 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
5152
feature_gate::EXPLAIN_ASM);
5253
}
5354

55+
let mut inline_asm = match parse_inline_asm(cx, sp, tts) {
56+
Ok(Some(inline_asm)) => inline_asm,
57+
Ok(None) => return DummyResult::expr(sp),
58+
Err(mut err) => {
59+
err.emit();
60+
return DummyResult::expr(sp);
61+
}
62+
};
63+
64+
// If there are no outputs, the inline assembly is executed just for its side effects,
65+
// so ensure that it is volatile
66+
if inline_asm.outputs.is_empty() {
67+
inline_asm.volatile = true;
68+
}
69+
70+
MacEager::expr(P(ast::Expr {
71+
id: ast::DUMMY_NODE_ID,
72+
node: ast::ExprKind::InlineAsm(P(inline_asm)),
73+
span: sp,
74+
attrs: ThinVec::new(),
75+
}))
76+
}
77+
78+
fn parse_inline_asm<'a>(
79+
cx: &mut ExtCtxt<'a>,
80+
sp: Span,
81+
tts: &[tokenstream::TokenTree],
82+
) -> Result<Option<ast::InlineAsm>, DiagnosticBuilder<'a>> {
5483
// Split the tts before the first colon, to avoid `asm!("x": y)` being
5584
// parsed as `asm!(z)` with `z = "x": y` which is type ascription.
5685
let first_colon = tts.iter()
@@ -80,22 +109,33 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
80109
if asm_str_style.is_some() {
81110
// If we already have a string with instructions,
82111
// ending up in Asm state again is an error.
83-
span_err!(cx, sp, E0660, "malformed inline assembly");
84-
return DummyResult::expr(sp);
112+
return Err(struct_span_err!(
113+
cx.parse_sess.span_diagnostic,
114+
sp,
115+
E0660,
116+
"malformed inline assembly"
117+
));
85118
}
86119
// Nested parser, stop before the first colon (see above).
87120
let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]);
88-
let (s, style) = match expr_to_string(cx,
89-
panictry!(p2.parse_expr()),
90-
"inline assembly must be a string literal") {
91-
Some((s, st)) => (s, st),
92-
// let compilation continue
93-
None => return DummyResult::expr(sp),
94-
};
121+
122+
if p2.token == token::Eof {
123+
let mut err =
124+
cx.struct_span_err(sp, "macro requires a string literal as an argument");
125+
err.span_label(sp, "string literal required");
126+
return Err(err);
127+
}
128+
129+
let expr = p2.parse_expr()?;
130+
let (s, style) =
131+
match expr_to_string(cx, expr, "inline assembly must be a string literal") {
132+
Some((s, st)) => (s, st),
133+
None => return Ok(None),
134+
};
95135

96136
// This is most likely malformed.
97137
if p2.token != token::Eof {
98-
let mut extra_tts = panictry!(p2.parse_all_token_trees());
138+
let mut extra_tts = p2.parse_all_token_trees()?;
99139
extra_tts.extend(tts[first_colon..].iter().cloned());
100140
p = parse::stream_to_parser(cx.parse_sess, extra_tts.into_iter().collect());
101141
}
@@ -105,18 +145,17 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
105145
}
106146
Outputs => {
107147
while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep {
108-
109148
if !outputs.is_empty() {
110149
p.eat(&token::Comma);
111150
}
112151

113-
let (constraint, _str_style) = panictry!(p.parse_str());
152+
let (constraint, _) = p.parse_str()?;
114153

115154
let span = p.prev_span;
116155

117-
panictry!(p.expect(&token::OpenDelim(token::Paren)));
118-
let out = panictry!(p.parse_expr());
119-
panictry!(p.expect(&token::CloseDelim(token::Paren)));
156+
p.expect(&token::OpenDelim(token::Paren))?;
157+
let expr = p.parse_expr()?;
158+
p.expect(&token::CloseDelim(token::Paren))?;
120159

121160
// Expands a read+write operand into two operands.
122161
//
@@ -143,20 +182,19 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
143182
let is_indirect = constraint_str.contains("*");
144183
outputs.push(ast::InlineAsmOutput {
145184
constraint: output.unwrap_or(constraint),
146-
expr: out,
185+
expr,
147186
is_rw,
148187
is_indirect,
149188
});
150189
}
151190
}
152191
Inputs => {
153192
while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep {
154-
155193
if !inputs.is_empty() {
156194
p.eat(&token::Comma);
157195
}
158196

159-
let (constraint, _str_style) = panictry!(p.parse_str());
197+
let (constraint, _) = p.parse_str()?;
160198

161199
if constraint.as_str().starts_with("=") {
162200
span_err!(cx, p.prev_span, E0662,
@@ -166,21 +204,20 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
166204
"input operand constraint contains '+'");
167205
}
168206

169-
panictry!(p.expect(&token::OpenDelim(token::Paren)));
170-
let input = panictry!(p.parse_expr());
171-
panictry!(p.expect(&token::CloseDelim(token::Paren)));
207+
p.expect(&token::OpenDelim(token::Paren))?;
208+
let input = p.parse_expr()?;
209+
p.expect(&token::CloseDelim(token::Paren))?;
172210

173211
inputs.push((constraint, input));
174212
}
175213
}
176214
Clobbers => {
177215
while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep {
178-
179216
if !clobs.is_empty() {
180217
p.eat(&token::Comma);
181218
}
182219

183-
let (s, _str_style) = panictry!(p.parse_str());
220+
let (s, _) = p.parse_str()?;
184221

185222
if OPTIONS.iter().any(|&opt| s == opt) {
186223
cx.span_warn(p.prev_span, "expected a clobber, found an option");
@@ -193,7 +230,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
193230
}
194231
}
195232
Options => {
196-
let (option, _str_style) = panictry!(p.parse_str());
233+
let (option, _) = p.parse_str()?;
197234

198235
if option == "volatile" {
199236
// Indicates that the inline assembly has side effects
@@ -234,26 +271,15 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
234271
}
235272
}
236273

237-
// If there are no outputs, the inline assembly is executed just for its side effects,
238-
// so ensure that it is volatile
239-
if outputs.is_empty() {
240-
volatile = true;
241-
}
242-
243-
MacEager::expr(P(ast::Expr {
244-
id: ast::DUMMY_NODE_ID,
245-
node: ast::ExprKind::InlineAsm(P(ast::InlineAsm {
246-
asm,
247-
asm_str_style: asm_str_style.unwrap(),
248-
outputs,
249-
inputs,
250-
clobbers: clobs,
251-
volatile,
252-
alignstack,
253-
dialect,
254-
ctxt: cx.backtrace(),
255-
})),
256-
span: sp,
257-
attrs: ThinVec::new(),
274+
Ok(Some(ast::InlineAsm {
275+
asm,
276+
asm_str_style: asm_str_style.unwrap(),
277+
outputs,
278+
inputs,
279+
clobbers: clobs,
280+
volatile,
281+
alignstack,
282+
dialect,
283+
ctxt: cx.backtrace(),
258284
}))
259285
}

src/libsyntax_ext/assert.rs

+44-24
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use syntax::ast::*;
1+
use errors::DiagnosticBuilder;
2+
use syntax::ast::{self, *};
23
use syntax::source_map::Spanned;
34
use syntax::ext::base::*;
45
use syntax::ext::build::AstBuilder;
56
use syntax::parse::token;
67
use syntax::print::pprust;
8+
use syntax::ptr::P;
79
use syntax::symbol::Symbol;
810
use syntax::tokenstream::{TokenStream, TokenTree};
911
use syntax_pos::{Span, DUMMY_SP};
@@ -13,33 +15,18 @@ pub fn expand_assert<'cx>(
1315
sp: Span,
1416
tts: &[TokenTree],
1517
) -> Box<dyn MacResult + 'cx> {
16-
let mut parser = cx.new_parser_from_tts(tts);
17-
18-
if parser.token == token::Eof {
19-
cx.struct_span_err(sp, "macro requires a boolean expression as an argument")
20-
.span_label(sp, "boolean expression required")
21-
.emit();
22-
return DummyResult::expr(sp);
23-
}
24-
25-
let cond_expr = panictry!(parser.parse_expr());
26-
let custom_msg_args = if parser.eat(&token::Comma) {
27-
let ts = parser.parse_tokens();
28-
if !ts.is_empty() {
29-
Some(ts)
30-
} else {
31-
None
18+
let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) {
19+
Ok(assert) => assert,
20+
Err(mut err) => {
21+
err.emit();
22+
return DummyResult::expr(sp);
3223
}
33-
} else {
34-
None
3524
};
3625

3726
let sp = sp.apply_mark(cx.current_expansion.mark);
3827
let panic_call = Mac_ {
3928
path: Path::from_ident(Ident::new(Symbol::intern("panic"), sp)),
40-
tts: if let Some(ts) = custom_msg_args {
41-
ts.into()
42-
} else {
29+
tts: custom_message.unwrap_or_else(|| {
4330
TokenStream::from(TokenTree::Token(
4431
DUMMY_SP,
4532
token::Literal(
@@ -49,8 +36,8 @@ pub fn expand_assert<'cx>(
4936
))),
5037
None,
5138
),
52-
)).into()
53-
},
39+
))
40+
}).into(),
5441
delim: MacDelimiter::Parenthesis,
5542
};
5643
let if_expr = cx.expr_if(
@@ -67,3 +54,36 @@ pub fn expand_assert<'cx>(
6754
);
6855
MacEager::expr(if_expr)
6956
}
57+
58+
struct Assert {
59+
cond_expr: P<ast::Expr>,
60+
custom_message: Option<TokenStream>,
61+
}
62+
63+
fn parse_assert<'a>(
64+
cx: &mut ExtCtxt<'a>,
65+
sp: Span,
66+
tts: &[TokenTree]
67+
) -> Result<Assert, DiagnosticBuilder<'a>> {
68+
let mut parser = cx.new_parser_from_tts(tts);
69+
70+
if parser.token == token::Eof {
71+
let mut err = cx.struct_span_err(sp, "macro requires a boolean expression as an argument");
72+
err.span_label(sp, "boolean expression required");
73+
return Err(err);
74+
}
75+
76+
Ok(Assert {
77+
cond_expr: parser.parse_expr()?,
78+
custom_message: if parser.eat(&token::Comma) {
79+
let ts = parser.parse_tokens();
80+
if !ts.is_empty() {
81+
Some(ts)
82+
} else {
83+
None
84+
}
85+
} else {
86+
None
87+
},
88+
})
89+
}

0 commit comments

Comments
 (0)