diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 3fa2d085ece..032b0fc9748 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -23,7 +23,7 @@ use syntax::json::JsonEmitter; use syntax::ptr::P; use syntax::symbol::keywords; use syntax_pos::DUMMY_SP; -use errors; +use errors::{self, FatalError}; use errors::emitter::{Emitter, EmitterWriter}; use parking_lot::ReentrantMutex; @@ -429,7 +429,13 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let control = &driver::CompileController::basic(); - let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input)); + let krate = match driver::phase_1_parse_input(control, &sess, &input) { + Ok(krate) => krate, + Err(mut e) => { + e.emit(); + FatalError.raise(); + } + }; let name = match crate_name { Some(ref crate_name) => crate_name.clone(), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 67d512ed71d..1b6d7e87192 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -32,7 +32,7 @@ extern crate rustc_metadata; extern crate rustc_target; extern crate rustc_typeck; extern crate serialize; -#[macro_use] extern crate syntax; +extern crate syntax; extern crate syntax_pos; extern crate test as testing; #[macro_use] extern crate log; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 24bb00f4112..dd9fbbb2546 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -1,4 +1,4 @@ -use errors; +use errors::{self, FatalError}; use errors::emitter::ColorConfig; use rustc_data_structures::sync::Lrc; use rustc_lint; @@ -84,9 +84,14 @@ pub fn run(mut options: Options) -> isize { target_features::add_configuration(&mut cfg, &sess, &*codegen_backend); sess.parse_sess.config = cfg; - let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(), - &sess, - &input)); + let krate = + match driver::phase_1_parse_input(&driver::CompileController::basic(), &sess, &input) { + Ok(krate) => krate, + Err(mut e) => { + e.emit(); + FatalError.raise(); + } + }; let driver::ExpansionResult { defs, mut hir_forest, .. } = { phase_2_configure_and_expand( &sess, diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index f1345d0e6f1..ea943e16a46 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -44,8 +44,6 @@ use ast::AttrId; // way towards a non-panic!-prone parser. It should be used for fatal parsing // errors; eventually we plan to convert all code using panictry to just use // normal try. -// Exported for syntax_ext, not meant for general use. -#[macro_export] macro_rules! panictry { ($e:expr) => ({ use std::result::Result::{Ok, Err}; diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index a8f3c40db60..41ee6e91b3d 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -4,6 +4,7 @@ use self::State::*; use rustc_data_structures::thin_vec::ThinVec; +use errors::DiagnosticBuilder; use syntax::ast; use syntax::ext::base; use syntax::ext::base::*; @@ -51,6 +52,34 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, feature_gate::EXPLAIN_ASM); } + let mut inline_asm = match parse_inline_asm(cx, sp, tts) { + Ok(Some(inline_asm)) => inline_asm, + Ok(None) => return DummyResult::expr(sp), + Err(mut err) => { + err.emit(); + return DummyResult::expr(sp); + } + }; + + // If there are no outputs, the inline assembly is executed just for its side effects, + // so ensure that it is volatile + if inline_asm.outputs.is_empty() { + inline_asm.volatile = true; + } + + MacEager::expr(P(ast::Expr { + id: ast::DUMMY_NODE_ID, + node: ast::ExprKind::InlineAsm(P(inline_asm)), + span: sp, + attrs: ThinVec::new(), + })) +} + +fn parse_inline_asm<'a>( + cx: &mut ExtCtxt<'a>, + sp: Span, + tts: &[tokenstream::TokenTree], +) -> Result, DiagnosticBuilder<'a>> { // Split the tts before the first colon, to avoid `asm!("x": y)` being // parsed as `asm!(z)` with `z = "x": y` which is type ascription. let first_colon = tts.iter() @@ -80,22 +109,33 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, if asm_str_style.is_some() { // If we already have a string with instructions, // ending up in Asm state again is an error. - span_err!(cx, sp, E0660, "malformed inline assembly"); - return DummyResult::expr(sp); + return Err(struct_span_err!( + cx.parse_sess.span_diagnostic, + sp, + E0660, + "malformed inline assembly" + )); } // Nested parser, stop before the first colon (see above). let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]); - let (s, style) = match expr_to_string(cx, - panictry!(p2.parse_expr()), - "inline assembly must be a string literal") { - Some((s, st)) => (s, st), - // let compilation continue - None => return DummyResult::expr(sp), - }; + + if p2.token == token::Eof { + let mut err = + cx.struct_span_err(sp, "macro requires a string literal as an argument"); + err.span_label(sp, "string literal required"); + return Err(err); + } + + let expr = p2.parse_expr()?; + let (s, style) = + match expr_to_string(cx, expr, "inline assembly must be a string literal") { + Some((s, st)) => (s, st), + None => return Ok(None), + }; // This is most likely malformed. if p2.token != token::Eof { - let mut extra_tts = panictry!(p2.parse_all_token_trees()); + let mut extra_tts = p2.parse_all_token_trees()?; extra_tts.extend(tts[first_colon..].iter().cloned()); p = parse::stream_to_parser(cx.parse_sess, extra_tts.into_iter().collect()); } @@ -105,18 +145,17 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, } Outputs => { while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep { - if !outputs.is_empty() { p.eat(&token::Comma); } - let (constraint, _str_style) = panictry!(p.parse_str()); + let (constraint, _) = p.parse_str()?; let span = p.prev_span; - panictry!(p.expect(&token::OpenDelim(token::Paren))); - let out = panictry!(p.parse_expr()); - panictry!(p.expect(&token::CloseDelim(token::Paren))); + p.expect(&token::OpenDelim(token::Paren))?; + let expr = p.parse_expr()?; + p.expect(&token::CloseDelim(token::Paren))?; // Expands a read+write operand into two operands. // @@ -143,7 +182,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, let is_indirect = constraint_str.contains("*"); outputs.push(ast::InlineAsmOutput { constraint: output.unwrap_or(constraint), - expr: out, + expr, is_rw, is_indirect, }); @@ -151,12 +190,11 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, } Inputs => { while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep { - if !inputs.is_empty() { p.eat(&token::Comma); } - let (constraint, _str_style) = panictry!(p.parse_str()); + let (constraint, _) = p.parse_str()?; if constraint.as_str().starts_with("=") { span_err!(cx, p.prev_span, E0662, @@ -166,21 +204,20 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, "input operand constraint contains '+'"); } - panictry!(p.expect(&token::OpenDelim(token::Paren))); - let input = panictry!(p.parse_expr()); - panictry!(p.expect(&token::CloseDelim(token::Paren))); + p.expect(&token::OpenDelim(token::Paren))?; + let input = p.parse_expr()?; + p.expect(&token::CloseDelim(token::Paren))?; inputs.push((constraint, input)); } } Clobbers => { while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep { - if !clobs.is_empty() { p.eat(&token::Comma); } - let (s, _str_style) = panictry!(p.parse_str()); + let (s, _) = p.parse_str()?; if OPTIONS.iter().any(|&opt| s == opt) { 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, } } Options => { - let (option, _str_style) = panictry!(p.parse_str()); + let (option, _) = p.parse_str()?; if option == "volatile" { // Indicates that the inline assembly has side effects @@ -234,26 +271,15 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, } } - // If there are no outputs, the inline assembly is executed just for its side effects, - // so ensure that it is volatile - if outputs.is_empty() { - volatile = true; - } - - MacEager::expr(P(ast::Expr { - id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::InlineAsm(P(ast::InlineAsm { - asm, - asm_str_style: asm_str_style.unwrap(), - outputs, - inputs, - clobbers: clobs, - volatile, - alignstack, - dialect, - ctxt: cx.backtrace(), - })), - span: sp, - attrs: ThinVec::new(), + Ok(Some(ast::InlineAsm { + asm, + asm_str_style: asm_str_style.unwrap(), + outputs, + inputs, + clobbers: clobs, + volatile, + alignstack, + dialect, + ctxt: cx.backtrace(), })) } diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index 2f5743e5e9b..b27f495322a 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -1,9 +1,11 @@ -use syntax::ast::*; +use errors::DiagnosticBuilder; +use syntax::ast::{self, *}; use syntax::source_map::Spanned; use syntax::ext::base::*; use syntax::ext::build::AstBuilder; use syntax::parse::token; use syntax::print::pprust; +use syntax::ptr::P; use syntax::symbol::Symbol; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax_pos::{Span, DUMMY_SP}; @@ -13,33 +15,18 @@ pub fn expand_assert<'cx>( sp: Span, tts: &[TokenTree], ) -> Box { - let mut parser = cx.new_parser_from_tts(tts); - - if parser.token == token::Eof { - cx.struct_span_err(sp, "macro requires a boolean expression as an argument") - .span_label(sp, "boolean expression required") - .emit(); - return DummyResult::expr(sp); - } - - let cond_expr = panictry!(parser.parse_expr()); - let custom_msg_args = if parser.eat(&token::Comma) { - let ts = parser.parse_tokens(); - if !ts.is_empty() { - Some(ts) - } else { - None + let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) { + Ok(assert) => assert, + Err(mut err) => { + err.emit(); + return DummyResult::expr(sp); } - } else { - None }; let sp = sp.apply_mark(cx.current_expansion.mark); let panic_call = Mac_ { path: Path::from_ident(Ident::new(Symbol::intern("panic"), sp)), - tts: if let Some(ts) = custom_msg_args { - ts.into() - } else { + tts: custom_message.unwrap_or_else(|| { TokenStream::from(TokenTree::Token( DUMMY_SP, token::Literal( @@ -49,8 +36,8 @@ pub fn expand_assert<'cx>( ))), None, ), - )).into() - }, + )) + }).into(), delim: MacDelimiter::Parenthesis, }; let if_expr = cx.expr_if( @@ -67,3 +54,36 @@ pub fn expand_assert<'cx>( ); MacEager::expr(if_expr) } + +struct Assert { + cond_expr: P, + custom_message: Option, +} + +fn parse_assert<'a>( + cx: &mut ExtCtxt<'a>, + sp: Span, + tts: &[TokenTree] +) -> Result> { + let mut parser = cx.new_parser_from_tts(tts); + + if parser.token == token::Eof { + let mut err = cx.struct_span_err(sp, "macro requires a boolean expression as an argument"); + err.span_label(sp, "boolean expression required"); + return Err(err); + } + + Ok(Assert { + cond_expr: parser.parse_expr()?, + custom_message: if parser.eat(&token::Comma) { + let ts = parser.parse_tokens(); + if !ts.is_empty() { + Some(ts) + } else { + None + } + } else { + None + }, + }) +} diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs index 7e3c1bbddf5..3b47b03cbe8 100644 --- a/src/libsyntax_ext/cfg.rs +++ b/src/libsyntax_ext/cfg.rs @@ -2,6 +2,8 @@ /// a literal `true` or `false` based on whether the given cfg matches the /// current compilation environment. +use errors::DiagnosticBuilder; +use syntax::ast; use syntax::ext::base::*; use syntax::ext::base; use syntax::ext::build::AstBuilder; @@ -15,16 +17,39 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt, tts: &[tokenstream::TokenTree]) -> Box { let sp = sp.apply_mark(cx.current_expansion.mark); + + match parse_cfg(cx, sp, tts) { + Ok(cfg) => { + let matches_cfg = attr::cfg_matches(&cfg, cx.parse_sess, cx.ecfg.features); + MacEager::expr(cx.expr_bool(sp, matches_cfg)) + } + Err(mut err) => { + err.emit(); + DummyResult::expr(sp) + } + } +} + +fn parse_cfg<'a>( + cx: &mut ExtCtxt<'a>, + sp: Span, + tts: &[tokenstream::TokenTree], +) -> Result> { let mut p = cx.new_parser_from_tts(tts); - let cfg = panictry!(p.parse_meta_item()); + + if p.token == token::Eof { + let mut err = cx.struct_span_err(sp, "macro requires a cfg-pattern as an argument"); + err.span_label(sp, "cfg-pattern required"); + return Err(err); + } + + let cfg = p.parse_meta_item()?; let _ = p.eat(&token::Comma); if !p.eat(&token::Eof) { - cx.span_err(sp, "expected 1 cfg-pattern"); - return DummyResult::expr(sp); + return Err(cx.struct_span_err(sp, "expected 1 cfg-pattern")); } - let matches_cfg = attr::cfg_matches(&cfg, cx.parse_sess, cx.ecfg.features); - MacEager::expr(cx.expr_bool(sp, matches_cfg)) + Ok(cfg) } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index c11f27f3ed5..61722ba5516 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -3,6 +3,7 @@ use self::Position::*; use fmt_macros as parse; +use errors::DiagnosticBuilder; use syntax::ast; use syntax::ext::base::{self, *}; use syntax::ext::build::AstBuilder; @@ -112,7 +113,7 @@ struct Context<'a, 'b: 'a> { is_literal: bool, } -/// Parses the arguments from the given list of tokens, returning None +/// Parses the arguments from the given list of tokens, returning the diagnostic /// if there's a parse error so we can continue parsing other format! /// expressions. /// @@ -121,27 +122,26 @@ struct Context<'a, 'b: 'a> { /// ```text /// Some((fmtstr, parsed arguments, index map for named arguments)) /// ``` -fn parse_args(ecx: &mut ExtCtxt, - sp: Span, - tts: &[tokenstream::TokenTree]) - -> Option<(P, Vec>, FxHashMap)> { +fn parse_args<'a>( + ecx: &mut ExtCtxt<'a>, + sp: Span, + tts: &[tokenstream::TokenTree] +) -> Result<(P, Vec>, FxHashMap), DiagnosticBuilder<'a>> { let mut args = Vec::>::new(); let mut names = FxHashMap::::default(); let mut p = ecx.new_parser_from_tts(tts); if p.token == token::Eof { - ecx.span_err(sp, "requires at least a format string argument"); - return None; + return Err(ecx.struct_span_err(sp, "requires at least a format string argument")); } - let fmtstr = panictry!(p.parse_expr()); + let fmtstr = p.parse_expr()?; let mut named = false; while p.token != token::Eof { if !p.eat(&token::Comma) { - ecx.span_err(p.span, "expected token: `,`"); - return None; + return Err(ecx.struct_span_err(p.span, "expected token: `,`")); } if p.token == token::Eof { break; @@ -152,16 +152,15 @@ fn parse_args(ecx: &mut ExtCtxt, p.bump(); i } else { - ecx.span_err( + return Err(ecx.struct_span_err( p.span, "expected ident, positional arguments cannot follow named arguments", - ); - return None; + )); }; let name: &str = &ident.as_str(); - panictry!(p.expect(&token::Eq)); - let e = panictry!(p.parse_expr()); + p.expect(&token::Eq).unwrap(); + let e = p.parse_expr()?; if let Some(prev) = names.get(name) { ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name)) .span_note(args[*prev].span, "previously here") @@ -177,10 +176,11 @@ fn parse_args(ecx: &mut ExtCtxt, names.insert(name.to_string(), slot); args.push(e); } else { - args.push(panictry!(p.parse_expr())); + let e = p.parse_expr()?; + args.push(e); } } - Some((fmtstr, args, names)) + Ok((fmtstr, args, names)) } impl<'a, 'b> Context<'a, 'b> { @@ -689,10 +689,13 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, -> Box { sp = sp.apply_mark(ecx.current_expansion.mark); match parse_args(ecx, sp, tts) { - Some((efmt, args, names)) => { + Ok((efmt, args, names)) => { MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, false)) } - None => DummyResult::expr(sp), + Err(mut err) => { + err.emit(); + DummyResult::expr(sp) + } } } @@ -716,10 +719,13 @@ pub fn expand_format_args_nl<'cx>( } sp = sp.apply_mark(ecx.current_expansion.mark); match parse_args(ecx, sp, tts) { - Some((efmt, args, names)) => { + Ok((efmt, args, names)) => { MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, true)) } - None => DummyResult::expr(sp), + Err(mut err) => { + err.emit(); + DummyResult::expr(sp) + } } } diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index a58c267ab4f..0a12e27c4fc 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -8,11 +8,13 @@ /// LLVM's `module asm "some assembly here"`. All of LLVM's caveats /// therefore apply. +use errors::DiagnosticBuilder; use syntax::ast; use syntax::source_map::respan; use syntax::ext::base; use syntax::ext::base::*; use syntax::feature_gate; +use syntax::parse::token; use syntax::ptr::P; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -31,24 +33,47 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt, feature_gate::EXPLAIN_GLOBAL_ASM); } + match parse_global_asm(cx, sp, tts) { + Ok(Some(global_asm)) => { + MacEager::items(smallvec![P(ast::Item { + ident: ast::Ident::with_empty_ctxt(Symbol::intern("")), + attrs: Vec::new(), + id: ast::DUMMY_NODE_ID, + node: ast::ItemKind::GlobalAsm(P(global_asm)), + vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), + span: sp, + tokens: None, + })]) + } + Ok(None) => DummyResult::any(sp), + Err(mut err) => { + err.emit(); + DummyResult::any(sp) + } + } +} + +fn parse_global_asm<'a>( + cx: &mut ExtCtxt<'a>, + sp: Span, + tts: &[tokenstream::TokenTree] +) -> Result, DiagnosticBuilder<'a>> { let mut p = cx.new_parser_from_tts(tts); - let (asm, _) = match expr_to_string(cx, - panictry!(p.parse_expr()), - "inline assembly must be a string literal") { + + if p.token == token::Eof { + let mut err = cx.struct_span_err(sp, "macro requires a string literal as an argument"); + err.span_label(sp, "string literal required"); + return Err(err); + } + + let expr = p.parse_expr()?; + let (asm, _) = match expr_to_string(cx, expr, "inline assembly must be a string literal") { Some((s, st)) => (s, st), - None => return DummyResult::any(sp), + None => return Ok(None), }; - MacEager::items(smallvec![P(ast::Item { - ident: ast::Ident::with_empty_ctxt(Symbol::intern("")), - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::GlobalAsm(P(ast::GlobalAsm { - asm, - ctxt: cx.backtrace(), - })), - vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), - span: sp, - tokens: None, - })]) + Ok(Some(ast::GlobalAsm { + asm, + ctxt: cx.backtrace(), + })) } diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout index 54830dceb8f..9fd46e94f03 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.stdout +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -12,7 +12,7 @@ error[E0425]: cannot find value `no` in this scope 3 | no | ^^ not found in this scope -thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:316:13 +thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:321:13 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. ---- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ---- @@ -21,7 +21,7 @@ thread '$DIR/failed-doctest-output.rs - SomeStruct (line 11)' panicked at 'test thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. -', src/librustdoc/test.rs:351:17 +', src/librustdoc/test.rs:356:17 failures: diff --git a/src/test/ui/asm/asm-parse-errors.rs b/src/test/ui/asm/asm-parse-errors.rs new file mode 100644 index 00000000000..e712ac5826e --- /dev/null +++ b/src/test/ui/asm/asm-parse-errors.rs @@ -0,0 +1,15 @@ +#![feature(asm)] + +fn main() { + asm!(); //~ ERROR requires a string literal as an argument + asm!("nop" : struct); //~ ERROR expected string literal + asm!("mov %eax, $$0x2" : struct); //~ ERROR expected string literal + asm!("mov %eax, $$0x2" : "={eax}" struct); //~ ERROR expected `(` + asm!("mov %eax, $$0x2" : "={eax}"(struct)); //~ ERROR expected expression + asm!("in %dx, %al" : "={al}"(result) : struct); //~ ERROR expected string literal + asm!("in %dx, %al" : "={al}"(result) : "{dx}" struct); //~ ERROR expected `(` + asm!("in %dx, %al" : "={al}"(result) : "{dx}"(struct)); //~ ERROR expected expression + asm!("mov $$0x200, %eax" : : : struct); //~ ERROR expected string literal + asm!("mov eax, 2" : "={eax}"(foo) : : : struct); //~ ERROR expected string literal + asm!(123); //~ ERROR inline assembly must be a string literal +} diff --git a/src/test/ui/asm/asm-parse-errors.stderr b/src/test/ui/asm/asm-parse-errors.stderr new file mode 100644 index 00000000000..37b61b80b2b --- /dev/null +++ b/src/test/ui/asm/asm-parse-errors.stderr @@ -0,0 +1,68 @@ +error: macro requires a string literal as an argument + --> $DIR/asm-parse-errors.rs:4:5 + | +LL | asm!(); //~ ERROR requires a string literal as an argument + | ^^^^^^^ string literal required + +error: expected string literal + --> $DIR/asm-parse-errors.rs:5:18 + | +LL | asm!("nop" : struct); //~ ERROR expected string literal + | ^^^^^^ expected string literal + +error: expected string literal + --> $DIR/asm-parse-errors.rs:6:30 + | +LL | asm!("mov %eax, $$0x2" : struct); //~ ERROR expected string literal + | ^^^^^^ expected string literal + +error: expected `(`, found keyword `struct` + --> $DIR/asm-parse-errors.rs:7:39 + | +LL | asm!("mov %eax, $$0x2" : "={eax}" struct); //~ ERROR expected `(` + | ^^^^^^ expected `(` + +error: expected expression, found keyword `struct` + --> $DIR/asm-parse-errors.rs:8:39 + | +LL | asm!("mov %eax, $$0x2" : "={eax}"(struct)); //~ ERROR expected expression + | ^^^^^^ expected expression + +error: expected string literal + --> $DIR/asm-parse-errors.rs:9:44 + | +LL | asm!("in %dx, %al" : "={al}"(result) : struct); //~ ERROR expected string literal + | ^^^^^^ expected string literal + +error: expected `(`, found keyword `struct` + --> $DIR/asm-parse-errors.rs:10:51 + | +LL | asm!("in %dx, %al" : "={al}"(result) : "{dx}" struct); //~ ERROR expected `(` + | ^^^^^^ expected `(` + +error: expected expression, found keyword `struct` + --> $DIR/asm-parse-errors.rs:11:51 + | +LL | asm!("in %dx, %al" : "={al}"(result) : "{dx}"(struct)); //~ ERROR expected expression + | ^^^^^^ expected expression + +error: expected string literal + --> $DIR/asm-parse-errors.rs:12:36 + | +LL | asm!("mov $$0x200, %eax" : : : struct); //~ ERROR expected string literal + | ^^^^^^ expected string literal + +error: expected string literal + --> $DIR/asm-parse-errors.rs:13:45 + | +LL | asm!("mov eax, 2" : "={eax}"(foo) : : : struct); //~ ERROR expected string literal + | ^^^^^^ expected string literal + +error: inline assembly must be a string literal + --> $DIR/asm-parse-errors.rs:14:10 + | +LL | asm!(123); //~ ERROR inline assembly must be a string literal + | ^^^ + +error: aborting due to 11 previous errors + diff --git a/src/test/ui/issues/issue-22644.rs b/src/test/ui/issues/issue-22644.rs index c87a927e550..9244ff5931d 100644 --- a/src/test/ui/issues/issue-22644.rs +++ b/src/test/ui/issues/issue-22644.rs @@ -1,5 +1,7 @@ +#![feature(type_ascription)] + fn main() { - let a : u32 = 0; + let a : usize = 0; let long_name : usize = 0; println!("{}", a as usize > long_name); diff --git a/src/test/ui/issues/issue-22644.stderr b/src/test/ui/issues/issue-22644.stderr index ea5c9c5ad23..de97b2271b1 100644 --- a/src/test/ui/issues/issue-22644.stderr +++ b/src/test/ui/issues/issue-22644.stderr @@ -1,5 +1,5 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison - --> $DIR/issue-22644.rs:6:31 + --> $DIR/issue-22644.rs:8:31 | LL | println!("{}", a as usize < long_name); //~ ERROR `<` is interpreted as a start of generic | ---------- ^ --------- interpreted as generic arguments @@ -8,7 +8,7 @@ LL | println!("{}", a as usize < long_name); //~ ERROR `<` is interpreted as | help: try comparing the cast value: `(a as usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison - --> $DIR/issue-22644.rs:7:33 + --> $DIR/issue-22644.rs:9:33 | LL | println!("{}{}", a as usize < long_name, long_name); | ---------- ^ -------------------- interpreted as generic arguments @@ -17,7 +17,7 @@ LL | println!("{}{}", a as usize < long_name, long_name); | help: try comparing the cast value: `(a as usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison - --> $DIR/issue-22644.rs:9:31 + --> $DIR/issue-22644.rs:11:31 | LL | println!("{}", a as usize < 4); //~ ERROR `<` is interpreted as a start of generic | ---------- ^ - interpreted as generic arguments @@ -26,7 +26,7 @@ LL | println!("{}", a as usize < 4); //~ ERROR `<` is interpreted as a start | help: try comparing the cast value: `(a as usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison - --> $DIR/issue-22644.rs:11:31 + --> $DIR/issue-22644.rs:13:31 | LL | println!("{}{}", a: usize < long_name, long_name); | -------- ^ -------------------- interpreted as generic arguments @@ -35,7 +35,7 @@ LL | println!("{}{}", a: usize < long_name, long_name); | help: try comparing the cast value: `(a: usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison - --> $DIR/issue-22644.rs:13:29 + --> $DIR/issue-22644.rs:15:29 | LL | println!("{}", a: usize < 4); //~ ERROR `<` is interpreted as a start of generic | -------- ^ - interpreted as generic arguments @@ -44,7 +44,7 @@ LL | println!("{}", a: usize < 4); //~ ERROR `<` is interpreted as a start o | help: try comparing the cast value: `(a: usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison - --> $DIR/issue-22644.rs:18:20 + --> $DIR/issue-22644.rs:20:20 | LL | < //~ ERROR `<` is interpreted as a start of generic | ^ not interpreted as comparison @@ -58,7 +58,7 @@ LL | usize) | error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison - --> $DIR/issue-22644.rs:27:20 + --> $DIR/issue-22644.rs:29:20 | LL | < //~ ERROR `<` is interpreted as a start of generic | ^ not interpreted as comparison @@ -75,7 +75,7 @@ LL | ... error: `<` is interpreted as a start of generic arguments for `usize`, not a shift - --> $DIR/issue-22644.rs:30:31 + --> $DIR/issue-22644.rs:32:31 | LL | println!("{}", a as usize << long_name); //~ ERROR `<` is interpreted as a start of generic | ---------- ^^ --------- interpreted as generic arguments @@ -84,7 +84,7 @@ LL | println!("{}", a as usize << long_name); //~ ERROR `<` is interpreted a | help: try shifting the cast value: `(a as usize)` error: expected type, found `4` - --> $DIR/issue-22644.rs:32:28 + --> $DIR/issue-22644.rs:34:28 | LL | println!("{}", a: &mut 4); //~ ERROR expected type, found `4` | ^ expecting a type here because of type ascription diff --git a/src/test/ui/macros/assert.rs b/src/test/ui/macros/assert.rs index 8732cb58d74..71b0dbb19e2 100644 --- a/src/test/ui/macros/assert.rs +++ b/src/test/ui/macros/assert.rs @@ -1,4 +1,6 @@ fn main() { assert!(); //~ ERROR requires a boolean expression + assert!(struct); //~ ERROR expected expression debug_assert!(); //~ ERROR requires a boolean expression + debug_assert!(struct); //~ ERROR expected expression } diff --git a/src/test/ui/macros/assert.stderr b/src/test/ui/macros/assert.stderr index 89faba0cf63..2cfcebabcb9 100644 --- a/src/test/ui/macros/assert.stderr +++ b/src/test/ui/macros/assert.stderr @@ -4,13 +4,25 @@ error: macro requires a boolean expression as an argument LL | assert!(); //~ ERROR requires a boolean expression | ^^^^^^^^^^ boolean expression required +error: expected expression, found keyword `struct` + --> $DIR/assert.rs:3:13 + | +LL | assert!(struct); //~ ERROR expected expression + | ^^^^^^ expected expression + error: macro requires a boolean expression as an argument - --> $DIR/assert.rs:3:5 + --> $DIR/assert.rs:4:5 | LL | debug_assert!(); //~ ERROR requires a boolean expression | ^^^^^^^^^^^^^^^^ boolean expression required | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: aborting due to 2 previous errors +error: expected expression, found keyword `struct` + --> $DIR/assert.rs:5:19 + | +LL | debug_assert!(struct); //~ ERROR expected expression + | ^^^^^^ expected expression + +error: aborting due to 4 previous errors diff --git a/src/test/ui/macros/cfg.rs b/src/test/ui/macros/cfg.rs new file mode 100644 index 00000000000..222161a8183 --- /dev/null +++ b/src/test/ui/macros/cfg.rs @@ -0,0 +1,5 @@ +fn main() { + cfg!(); //~ ERROR macro requires a cfg-pattern + cfg!(123); //~ ERROR expected identifier + cfg!(foo = 123); //~ ERROR literal in `cfg` predicate value must be a string +} diff --git a/src/test/ui/macros/cfg.stderr b/src/test/ui/macros/cfg.stderr new file mode 100644 index 00000000000..a7aca88f3e5 --- /dev/null +++ b/src/test/ui/macros/cfg.stderr @@ -0,0 +1,21 @@ +error: macro requires a cfg-pattern as an argument + --> $DIR/cfg.rs:2:5 + | +LL | cfg!(); //~ ERROR macro requires a cfg-pattern + | ^^^^^^^ cfg-pattern required + +error: expected identifier, found `123` + --> $DIR/cfg.rs:3:10 + | +LL | cfg!(123); //~ ERROR expected identifier + | ^^^ expected identifier + +error[E0565]: literal in `cfg` predicate value must be a string + --> $DIR/cfg.rs:4:16 + | +LL | cfg!(foo = 123); //~ ERROR literal in `cfg` predicate value must be a string + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0565`. diff --git a/src/test/ui/macros/format-parse-errors.rs b/src/test/ui/macros/format-parse-errors.rs new file mode 100644 index 00000000000..ba1e441fe33 --- /dev/null +++ b/src/test/ui/macros/format-parse-errors.rs @@ -0,0 +1,10 @@ +fn main() { + format!(); //~ ERROR requires at least a format string argument + format!(struct); //~ ERROR expected expression + format!("s", name =); //~ ERROR expected expression + format!("s", foo = struct); //~ ERROR expected expression + format!("s", struct); //~ ERROR expected expression + + // This error should come after parsing errors to ensure they are non-fatal. + format!(123); //~ ERROR format argument must be a string literal +} diff --git a/src/test/ui/macros/format-parse-errors.stderr b/src/test/ui/macros/format-parse-errors.stderr new file mode 100644 index 00000000000..0463c548901 --- /dev/null +++ b/src/test/ui/macros/format-parse-errors.stderr @@ -0,0 +1,44 @@ +error: requires at least a format string argument + --> $DIR/format-parse-errors.rs:2:5 + | +LL | format!(); //~ ERROR requires at least a format string argument + | ^^^^^^^^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: expected expression, found keyword `struct` + --> $DIR/format-parse-errors.rs:3:13 + | +LL | format!(struct); //~ ERROR expected expression + | ^^^^^^ expected expression + +error: expected expression, found `` + --> $DIR/format-parse-errors.rs:4:23 + | +LL | format!("s", name =); //~ ERROR expected expression + | ^ expected expression + +error: expected expression, found keyword `struct` + --> $DIR/format-parse-errors.rs:5:24 + | +LL | format!("s", foo = struct); //~ ERROR expected expression + | ^^^^^^ expected expression + +error: expected expression, found keyword `struct` + --> $DIR/format-parse-errors.rs:6:18 + | +LL | format!("s", struct); //~ ERROR expected expression + | ^^^^^^ expected expression + +error: format argument must be a string literal + --> $DIR/format-parse-errors.rs:9:13 + | +LL | format!(123); //~ ERROR format argument must be a string literal + | ^^^ +help: you might be missing a string literal to format with + | +LL | format!("{}", 123); //~ ERROR format argument must be a string literal + | ^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/macros/global-asm.rs b/src/test/ui/macros/global-asm.rs new file mode 100644 index 00000000000..8402afa5085 --- /dev/null +++ b/src/test/ui/macros/global-asm.rs @@ -0,0 +1,7 @@ +#![feature(global_asm)] + +fn main() { + global_asm!(); //~ ERROR requires a string literal as an argument + global_asm!(struct); //~ ERROR expected expression + global_asm!(123); //~ ERROR inline assembly must be a string literal +} diff --git a/src/test/ui/macros/global-asm.stderr b/src/test/ui/macros/global-asm.stderr new file mode 100644 index 00000000000..94664c96db3 --- /dev/null +++ b/src/test/ui/macros/global-asm.stderr @@ -0,0 +1,20 @@ +error: macro requires a string literal as an argument + --> $DIR/global-asm.rs:4:5 + | +LL | global_asm!(); //~ ERROR requires a string literal as an argument + | ^^^^^^^^^^^^^^ string literal required + +error: expected expression, found keyword `struct` + --> $DIR/global-asm.rs:5:17 + | +LL | global_asm!(struct); //~ ERROR expected expression + | ^^^^^^ expected expression + +error: inline assembly must be a string literal + --> $DIR/global-asm.rs:6:17 + | +LL | global_asm!(123); //~ ERROR inline assembly must be a string literal + | ^^^ + +error: aborting due to 3 previous errors +