Auto merge of #52394 - estebank:println, r=oli-obk
Improve suggestion for missing fmt str in println Avoid using `concat!(fmt, "\n")` to improve the diagnostics being emitted when the first `println!()` argument isn't a formatting string literal. Fix #52347.
This commit is contained in:
commit
3d51086303
|
@ -150,12 +150,17 @@ pub struct Parser<'a> {
|
|||
pub errors: Vec<ParseError>,
|
||||
/// Current position of implicit positional argument pointer
|
||||
curarg: usize,
|
||||
/// `Some(raw count)` when the string is "raw", used to position spans correctly
|
||||
style: Option<usize>,
|
||||
/// How many newlines have been seen in the string so far, to adjust the error spans
|
||||
seen_newlines: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Parser<'a> {
|
||||
type Item = Piece<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Piece<'a>> {
|
||||
let raw = self.style.map(|raw| raw + self.seen_newlines).unwrap_or(0);
|
||||
if let Some(&(pos, c)) = self.cur.peek() {
|
||||
match c {
|
||||
'{' => {
|
||||
|
@ -170,20 +175,24 @@ impl<'a> Iterator for Parser<'a> {
|
|||
}
|
||||
'}' => {
|
||||
self.cur.next();
|
||||
let pos = pos + 1;
|
||||
if self.consume('}') {
|
||||
Some(String(self.string(pos)))
|
||||
Some(String(self.string(pos + 1)))
|
||||
} else {
|
||||
let err_pos = pos + raw + 1;
|
||||
self.err_with_note(
|
||||
"unmatched `}` found",
|
||||
"unmatched `}`",
|
||||
"if you intended to print `}`, you can escape it using `}}`",
|
||||
pos,
|
||||
pos,
|
||||
err_pos,
|
||||
err_pos,
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
'\n' => {
|
||||
self.seen_newlines += 1;
|
||||
Some(String(self.string(pos)))
|
||||
}
|
||||
_ => Some(String(self.string(pos))),
|
||||
}
|
||||
} else {
|
||||
|
@ -194,12 +203,14 @@ impl<'a> Iterator for Parser<'a> {
|
|||
|
||||
impl<'a> Parser<'a> {
|
||||
/// Creates a new parser for the given format string
|
||||
pub fn new(s: &'a str) -> Parser<'a> {
|
||||
pub fn new(s: &'a str, style: Option<usize>) -> Parser<'a> {
|
||||
Parser {
|
||||
input: s,
|
||||
cur: s.char_indices().peekable(),
|
||||
errors: vec![],
|
||||
curarg: 0,
|
||||
style,
|
||||
seen_newlines: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,24 +273,32 @@ impl<'a> Parser<'a> {
|
|||
/// found, an error is emitted.
|
||||
fn must_consume(&mut self, c: char) {
|
||||
self.ws();
|
||||
let raw = self.style.unwrap_or(0);
|
||||
|
||||
let padding = raw + self.seen_newlines;
|
||||
if let Some(&(pos, maybe)) = self.cur.peek() {
|
||||
if c == maybe {
|
||||
self.cur.next();
|
||||
} else {
|
||||
let pos = pos + padding + 1;
|
||||
self.err(format!("expected `{:?}`, found `{:?}`", c, maybe),
|
||||
format!("expected `{}`", c),
|
||||
pos + 1,
|
||||
pos + 1);
|
||||
pos,
|
||||
pos);
|
||||
}
|
||||
} else {
|
||||
let msg = format!("expected `{:?}` but string was terminated", c);
|
||||
let pos = self.input.len() + 1; // point at closing `"`
|
||||
// point at closing `"`, unless the last char is `\n` to account for `println`
|
||||
let pos = match self.input.chars().last() {
|
||||
Some('\n') => self.input.len(),
|
||||
_ => self.input.len() + 1,
|
||||
};
|
||||
if c == '}' {
|
||||
self.err_with_note(msg,
|
||||
format!("expected `{:?}`", c),
|
||||
"if you intended to print `{`, you can escape it using `{{`",
|
||||
pos,
|
||||
pos);
|
||||
pos + padding,
|
||||
pos + padding);
|
||||
} else {
|
||||
self.err(msg, format!("expected `{:?}`", c), pos, pos);
|
||||
}
|
||||
|
@ -536,7 +555,7 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
fn same(fmt: &'static str, p: &[Piece<'static>]) {
|
||||
let parser = Parser::new(fmt);
|
||||
let parser = Parser::new(fmt, None);
|
||||
assert!(parser.collect::<Vec<Piece<'static>>>() == p);
|
||||
}
|
||||
|
||||
|
@ -552,7 +571,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn musterr(s: &str) {
|
||||
let mut p = Parser::new(s);
|
||||
let mut p = Parser::new(s, None);
|
||||
p.next();
|
||||
assert!(!p.errors.is_empty());
|
||||
}
|
||||
|
|
|
@ -242,7 +242,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
|||
{
|
||||
let name = tcx.item_name(trait_def_id);
|
||||
let generics = tcx.generics_of(trait_def_id);
|
||||
let parser = Parser::new(&self.0);
|
||||
let parser = Parser::new(&self.0, None);
|
||||
let mut result = Ok(());
|
||||
for token in parser {
|
||||
match token {
|
||||
|
@ -298,7 +298,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
|||
Some((name, value))
|
||||
}).collect::<FxHashMap<String, String>>();
|
||||
|
||||
let parser = Parser::new(&self.0);
|
||||
let parser = Parser::new(&self.0, None);
|
||||
parser.map(|p| {
|
||||
match p {
|
||||
Piece::String(s) => s,
|
||||
|
|
|
@ -153,10 +153,17 @@ macro_rules! print {
|
|||
/// ```
|
||||
#[macro_export]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow_internal_unstable]
|
||||
macro_rules! println {
|
||||
() => (print!("\n"));
|
||||
($fmt:expr) => (print!(concat!($fmt, "\n")));
|
||||
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
|
||||
($($arg:tt)*) => ({
|
||||
#[cfg(not(stage0))] {
|
||||
($crate::io::_print(format_args_nl!($($arg)*)));
|
||||
}
|
||||
#[cfg(stage0)] {
|
||||
print!("{}\n", format_args!($($arg)*))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Macro for printing to the standard error.
|
||||
|
@ -210,10 +217,17 @@ macro_rules! eprint {
|
|||
/// ```
|
||||
#[macro_export]
|
||||
#[stable(feature = "eprint", since = "1.19.0")]
|
||||
#[allow_internal_unstable]
|
||||
macro_rules! eprintln {
|
||||
() => (eprint!("\n"));
|
||||
($fmt:expr) => (eprint!(concat!($fmt, "\n")));
|
||||
($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*));
|
||||
($($arg:tt)*) => ({
|
||||
#[cfg(all(not(stage0), not(stage1)))] {
|
||||
($crate::io::_eprint(format_args_nl!($($arg)*)));
|
||||
}
|
||||
#[cfg(any(stage0, stage1))] {
|
||||
eprint!("{}\n", format_args!($($arg)*))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
|
|
@ -959,29 +959,34 @@ impl<'a> ExtCtxt<'a> {
|
|||
/// Extract a string literal from the macro expanded version of `expr`,
|
||||
/// emitting `err_msg` if `expr` is not a string literal. This does not stop
|
||||
/// compilation on error, merely emits a non-fatal error and returns None.
|
||||
pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
|
||||
-> Option<Spanned<(Symbol, ast::StrStyle)>> {
|
||||
pub fn expr_to_spanned_string<'a>(
|
||||
cx: &'a mut ExtCtxt,
|
||||
expr: P<ast::Expr>,
|
||||
err_msg: &str,
|
||||
) -> Result<Spanned<(Symbol, ast::StrStyle)>, DiagnosticBuilder<'a>> {
|
||||
// Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
|
||||
let expr = expr.map(|mut expr| {
|
||||
expr.span = expr.span.apply_mark(cx.current_expansion.mark);
|
||||
expr
|
||||
});
|
||||
|
||||
// we want to be able to handle e.g. concat("foo", "bar")
|
||||
// we want to be able to handle e.g. `concat!("foo", "bar")`
|
||||
let expr = cx.expander().fold_expr(expr);
|
||||
match expr.node {
|
||||
Err(match expr.node {
|
||||
ast::ExprKind::Lit(ref l) => match l.node {
|
||||
ast::LitKind::Str(s, style) => return Some(respan(expr.span, (s, style))),
|
||||
_ => cx.span_err(l.span, err_msg)
|
||||
ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))),
|
||||
_ => cx.struct_span_err(l.span, err_msg)
|
||||
},
|
||||
_ => cx.span_err(expr.span, err_msg)
|
||||
}
|
||||
None
|
||||
_ => cx.struct_span_err(expr.span, err_msg)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
|
||||
-> Option<(Symbol, ast::StrStyle)> {
|
||||
expr_to_spanned_string(cx, expr, err_msg).map(|s| s.node)
|
||||
expr_to_spanned_string(cx, expr, err_msg)
|
||||
.map_err(|mut err| err.emit())
|
||||
.ok()
|
||||
.map(|s| s.node)
|
||||
}
|
||||
|
||||
/// Non-fatally assert that `tts` is empty. Note that this function
|
||||
|
|
|
@ -1609,6 +1609,7 @@ impl<'feat> ExpansionConfig<'feat> {
|
|||
fn enable_trace_macros = trace_macros,
|
||||
fn enable_allow_internal_unstable = allow_internal_unstable,
|
||||
fn enable_custom_derive = custom_derive,
|
||||
fn enable_format_args_nl = format_args_nl,
|
||||
fn use_extern_macros_enabled = use_extern_macros,
|
||||
fn macros_in_extern_enabled = macros_in_extern,
|
||||
fn proc_macro_mod = proc_macro_mod,
|
||||
|
|
|
@ -129,6 +129,7 @@ declare_features! (
|
|||
// rustc internal, for now:
|
||||
(active, intrinsics, "1.0.0", None, None),
|
||||
(active, lang_items, "1.0.0", None, None),
|
||||
(active, format_args_nl, "1.29.0", None, None),
|
||||
|
||||
(active, link_llvm_intrinsics, "1.0.0", Some(29602), None),
|
||||
(active, linkage, "1.0.0", Some(29603), None),
|
||||
|
@ -1320,6 +1321,9 @@ pub const EXPLAIN_LOG_SYNTAX: &'static str =
|
|||
pub const EXPLAIN_CONCAT_IDENTS: &'static str =
|
||||
"`concat_idents` is not stable enough for use and is subject to change";
|
||||
|
||||
pub const EXPLAIN_FORMAT_ARGS_NL: &'static str =
|
||||
"`format_args_nl` is only for internal language 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";
|
||||
pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
|
||||
|
|
|
@ -27,6 +27,7 @@ pub fn expand_syntax_ext(
|
|||
None => return base::DummyResult::expr(sp),
|
||||
};
|
||||
let mut accumulator = String::new();
|
||||
let mut missing_literal = vec![];
|
||||
for e in es {
|
||||
match e.node {
|
||||
ast::ExprKind::Lit(ref lit) => match lit.node {
|
||||
|
@ -51,17 +52,15 @@ pub fn expand_syntax_ext(
|
|||
}
|
||||
},
|
||||
_ => {
|
||||
let mut err = cx.struct_span_err(e.span, "expected a literal");
|
||||
let snippet = cx.codemap().span_to_snippet(e.span).unwrap();
|
||||
err.span_suggestion(
|
||||
e.span,
|
||||
"you might be missing a string literal to format with",
|
||||
format!("\"{{}}\", {}", snippet),
|
||||
);
|
||||
missing_literal.push(e.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
if missing_literal.len() > 0 {
|
||||
let mut err = cx.struct_span_err(missing_literal, "expected a literal");
|
||||
err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`");
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
let sp = sp.apply_mark(cx.current_expansion.mark);
|
||||
base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use syntax::ast;
|
|||
use syntax::ext::base::*;
|
||||
use syntax::ext::base;
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::feature_gate;
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
use syntax::symbol::Symbol;
|
||||
|
@ -683,7 +684,34 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt,
|
|||
sp = sp.apply_mark(ecx.current_expansion.mark);
|
||||
match parse_args(ecx, sp, tts) {
|
||||
Some((efmt, args, names)) => {
|
||||
MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names))
|
||||
MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, false))
|
||||
}
|
||||
None => DummyResult::expr(sp),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_format_args_nl<'cx>(ecx: &'cx mut ExtCtxt,
|
||||
mut sp: Span,
|
||||
tts: &[tokenstream::TokenTree])
|
||||
-> Box<dyn base::MacResult + 'cx> {
|
||||
//if !ecx.ecfg.enable_allow_internal_unstable() {
|
||||
|
||||
// For some reason, the only one that actually works for `println` is the first check
|
||||
if !sp.allows_unstable() // the enclosing span is marked as `#[allow_insternal_unsable]`
|
||||
&& !ecx.ecfg.enable_allow_internal_unstable() // NOTE: when is this enabled?
|
||||
&& !ecx.ecfg.enable_format_args_nl() // enabled using `#[feature(format_args_nl]`
|
||||
{
|
||||
feature_gate::emit_feature_err(&ecx.parse_sess,
|
||||
"format_args_nl",
|
||||
sp,
|
||||
feature_gate::GateIssue::Language,
|
||||
feature_gate::EXPLAIN_FORMAT_ARGS_NL);
|
||||
return base::DummyResult::expr(sp);
|
||||
}
|
||||
sp = sp.apply_mark(ecx.current_expansion.mark);
|
||||
match parse_args(ecx, sp, tts) {
|
||||
Some((efmt, args, names)) => {
|
||||
MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, true))
|
||||
}
|
||||
None => DummyResult::expr(sp),
|
||||
}
|
||||
|
@ -695,7 +723,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||
sp: Span,
|
||||
efmt: P<ast::Expr>,
|
||||
args: Vec<P<ast::Expr>>,
|
||||
names: HashMap<String, usize>)
|
||||
names: HashMap<String, usize>,
|
||||
append_newline: bool)
|
||||
-> P<ast::Expr> {
|
||||
// NOTE: this verbose way of initializing `Vec<Vec<ArgumentType>>` is because
|
||||
// `ArgumentType` does not derive `Clone`.
|
||||
|
@ -703,10 +732,28 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||
let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
|
||||
let mut macsp = ecx.call_site();
|
||||
macsp = macsp.apply_mark(ecx.current_expansion.mark);
|
||||
let msg = "format argument must be a string literal.";
|
||||
let msg = "format argument must be a string literal";
|
||||
let fmt_sp = efmt.span;
|
||||
let fmt = match expr_to_spanned_string(ecx, efmt, msg) {
|
||||
Some(fmt) => fmt,
|
||||
None => return DummyResult::raw_expr(sp),
|
||||
Ok(mut fmt) if append_newline => {
|
||||
fmt.node.0 = Symbol::intern(&format!("{}\n", fmt.node.0));
|
||||
fmt
|
||||
}
|
||||
Ok(fmt) => fmt,
|
||||
Err(mut err) => {
|
||||
let sugg_fmt = match args.len() {
|
||||
0 => "{}".to_string(),
|
||||
_ => format!("{}{{}}", "{} ".repeat(args.len())),
|
||||
|
||||
};
|
||||
err.span_suggestion(
|
||||
fmt_sp.shrink_to_lo(),
|
||||
"you might be missing a string literal to format with",
|
||||
format!("\"{}\", ", sugg_fmt),
|
||||
);
|
||||
err.emit();
|
||||
return DummyResult::raw_expr(sp);
|
||||
},
|
||||
};
|
||||
|
||||
let mut cx = Context {
|
||||
|
@ -731,7 +778,11 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||
};
|
||||
|
||||
let fmt_str = &*fmt.node.0.as_str();
|
||||
let mut parser = parse::Parser::new(fmt_str);
|
||||
let str_style = match fmt.node.1 {
|
||||
ast::StrStyle::Cooked => None,
|
||||
ast::StrStyle::Raw(raw) => Some(raw as usize),
|
||||
};
|
||||
let mut parser = parse::Parser::new(fmt_str, str_style);
|
||||
let mut pieces = vec![];
|
||||
|
||||
while let Some(mut piece) = parser.next() {
|
||||
|
@ -818,7 +869,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||
errs.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
|
||||
"multiple unused formatting arguments"
|
||||
);
|
||||
diag.span_label(cx.fmtsp, "multiple unused arguments in this statement");
|
||||
diag.span_label(cx.fmtsp, "multiple missing formatting arguments");
|
||||
diag
|
||||
}
|
||||
};
|
||||
|
@ -861,8 +912,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||
}
|
||||
|
||||
if show_doc_note {
|
||||
diag.note(concat!(stringify!($kind), " formatting not supported; see \
|
||||
the documentation for `std::fmt`"));
|
||||
diag.note(concat!(
|
||||
stringify!($kind),
|
||||
" formatting not supported; see the documentation for `std::fmt`",
|
||||
));
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
|
|
@ -139,6 +139,16 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
|
|||
unstable_feature: None,
|
||||
edition: hygiene::default_edition(),
|
||||
});
|
||||
register(Symbol::intern("format_args_nl"),
|
||||
NormalTT {
|
||||
expander: Box::new(format::expand_format_args_nl),
|
||||
def_info: None,
|
||||
allow_internal_unstable: true,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition: hygiene::default_edition(),
|
||||
});
|
||||
|
||||
for (name, ext) in user_exts {
|
||||
register(name, ext);
|
||||
|
|
|
@ -28,25 +28,19 @@ LL | println!("{}", FOO);
|
|||
| ^^^ referenced constant has errors
|
||||
|
||||
error[E0080]: referenced constant has errors
|
||||
--> $DIR/conditional_array_execution.rs:19:5
|
||||
--> $DIR/conditional_array_execution.rs:19:14
|
||||
|
|
||||
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
|
||||
| ----- attempt to subtract with overflow
|
||||
...
|
||||
LL | println!("{}", FOO);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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[E0080]: erroneous constant used
|
||||
--> $DIR/conditional_array_execution.rs:19:5
|
||||
--> $DIR/conditional_array_execution.rs:19:14
|
||||
|
|
||||
LL | println!("{}", FOO);
|
||||
| ^^^^^^^^^^^^^^^---^^
|
||||
| |
|
||||
| referenced constant has errors
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
| ^^^^ --- referenced constant has errors
|
||||
|
||||
error[E0080]: referenced constant has errors
|
||||
--> $DIR/conditional_array_execution.rs:19:20
|
||||
|
|
|
@ -51,25 +51,19 @@ LL | println!("{} {}", X, Y);
|
|||
| ^ referenced constant has errors
|
||||
|
||||
error[E0080]: referenced constant has errors
|
||||
--> $DIR/issue-43197.rs:24:5
|
||||
--> $DIR/issue-43197.rs:24:14
|
||||
|
|
||||
LL | const X: u32 = 0-1;
|
||||
| --- attempt to subtract with overflow
|
||||
...
|
||||
LL | println!("{} {}", X, Y);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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[E0080]: erroneous constant used
|
||||
--> $DIR/issue-43197.rs:24:5
|
||||
--> $DIR/issue-43197.rs:24:14
|
||||
|
|
||||
LL | println!("{} {}", X, Y);
|
||||
| ^^^^^^^^^^^^^^^^^^-^^^^^
|
||||
| |
|
||||
| referenced constant has errors
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
| ^^^^^^^ - referenced constant has errors
|
||||
|
||||
error[E0080]: referenced constant has errors
|
||||
--> $DIR/issue-43197.rs:24:26
|
||||
|
|
|
@ -1,23 +1,17 @@
|
|||
error[E0080]: referenced constant has errors
|
||||
--> $DIR/issue-44578.rs:35:5
|
||||
--> $DIR/issue-44578.rs:35:14
|
||||
|
|
||||
LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
|
||||
| ------------------------------------ index out of bounds: the len is 1 but the index is 1
|
||||
...
|
||||
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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[E0080]: erroneous constant used
|
||||
--> $DIR/issue-44578.rs:35:5
|
||||
--> $DIR/issue-44578.rs:35:14
|
||||
|
|
||||
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
|
||||
| ^^^^^^^^^^^^^^^--------------------------^^
|
||||
| |
|
||||
| referenced constant has errors
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
| ^^^^ -------------------------- referenced constant has errors
|
||||
|
||||
error[E0080]: referenced constant has errors
|
||||
--> $DIR/issue-44578.rs:35:20
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2018 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
format_args_nl!(""); //~ ERROR `format_args_nl` is only for internal language use
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
error[E0658]: `format_args_nl` is only for internal language use and is subject to change
|
||||
--> $DIR/feature-gate-format_args_nl.rs:12:5
|
||||
|
|
||||
LL | format_args_nl!(""); //~ ERROR `format_args_nl` is only for internal language use
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(format_args_nl)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -8,10 +8,14 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-tidy-tab
|
||||
|
||||
fn main() {
|
||||
println!("{");
|
||||
//~^ ERROR invalid format string: expected `'}'` but string was terminated
|
||||
println!("{{}}");
|
||||
println!("}");
|
||||
//~^ ERROR invalid format string: unmatched `}` found
|
||||
let _ = format!("{_foo}", _foo = 6usize);
|
||||
//~^ ERROR invalid format string: invalid argument name `_foo`
|
||||
let _ = format!("{_}", _ = 6usize);
|
||||
|
@ -22,4 +26,36 @@ fn main() {
|
|||
//~^ ERROR invalid format string: unmatched `}` found
|
||||
let _ = format!("{\\}");
|
||||
//~^ ERROR invalid format string: expected `'}'`, found `'\\'`
|
||||
let _ = format!("\n\n\n{\n\n\n");
|
||||
//~^ ERROR invalid format string
|
||||
let _ = format!(r###"
|
||||
|
||||
|
||||
|
||||
{"###);
|
||||
//~^ ERROR invalid format string
|
||||
let _ = format!(r###"
|
||||
|
||||
|
||||
|
||||
{
|
||||
|
||||
"###);
|
||||
//~^^ ERROR invalid format string
|
||||
let _ = format!(r###"
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
"###);
|
||||
//~^^^ ERROR invalid format string
|
||||
let _ = format!(r###"
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
"###);
|
||||
//~^^^ ERROR invalid format string: unmatched `}` found
|
||||
}
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
error: invalid format string: expected `'}'` but string was terminated
|
||||
--> $DIR/format-string-error.rs:12:5
|
||||
--> $DIR/format-string-error.rs:14:16
|
||||
|
|
||||
LL | println!("{");
|
||||
| ^^^^^^^^^^^^^^ expected `'}'` in format string
|
||||
| ^ expected `'}'` in format string
|
||||
|
|
||||
= note: if you intended to print `{`, you can escape it using `{{`
|
||||
= 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: invalid format string: unmatched `}` found
|
||||
--> $DIR/format-string-error.rs:14:5
|
||||
--> $DIR/format-string-error.rs:17:15
|
||||
|
|
||||
LL | println!("}");
|
||||
| ^^^^^^^^^^^^^^ unmatched `}` in format string
|
||||
| ^ unmatched `}` in format string
|
||||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
= 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: invalid format string: invalid argument name `_foo`
|
||||
--> $DIR/format-string-error.rs:15:23
|
||||
--> $DIR/format-string-error.rs:19:23
|
||||
|
|
||||
LL | let _ = format!("{_foo}", _foo = 6usize);
|
||||
| ^^^^ invalid argument name in format string
|
||||
|
@ -25,7 +23,7 @@ LL | let _ = format!("{_foo}", _foo = 6usize);
|
|||
= note: argument names cannot start with an underscore
|
||||
|
||||
error: invalid format string: invalid argument name `_`
|
||||
--> $DIR/format-string-error.rs:17:23
|
||||
--> $DIR/format-string-error.rs:21:23
|
||||
|
|
||||
LL | let _ = format!("{_}", _ = 6usize);
|
||||
| ^ invalid argument name in format string
|
||||
|
@ -33,7 +31,7 @@ LL | let _ = format!("{_}", _ = 6usize);
|
|||
= note: argument names cannot start with an underscore
|
||||
|
||||
error: invalid format string: expected `'}'` but string was terminated
|
||||
--> $DIR/format-string-error.rs:19:23
|
||||
--> $DIR/format-string-error.rs:23:23
|
||||
|
|
||||
LL | let _ = format!("{");
|
||||
| ^ expected `'}'` in format string
|
||||
|
@ -41,7 +39,7 @@ LL | let _ = format!("{");
|
|||
= note: if you intended to print `{`, you can escape it using `{{`
|
||||
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/format-string-error.rs:21:22
|
||||
--> $DIR/format-string-error.rs:25:22
|
||||
|
|
||||
LL | let _ = format!("}");
|
||||
| ^ unmatched `}` in format string
|
||||
|
@ -49,10 +47,50 @@ LL | let _ = format!("}");
|
|||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
|
||||
error: invalid format string: expected `'}'`, found `'/'`
|
||||
--> $DIR/format-string-error.rs:23:23
|
||||
--> $DIR/format-string-error.rs:27:23
|
||||
|
|
||||
LL | let _ = format!("{/}");
|
||||
| ^ expected `}` in format string
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: invalid format string: expected `'}'` but string was terminated
|
||||
--> $DIR/format-string-error.rs:29:29
|
||||
|
|
||||
LL | let _ = format!("/n/n/n{/n/n/n");
|
||||
| ^ expected `'}'` in format string
|
||||
|
|
||||
= note: if you intended to print `{`, you can escape it using `{{`
|
||||
|
||||
error: invalid format string: expected `'}'` but string was terminated
|
||||
--> $DIR/format-string-error.rs:35:3
|
||||
|
|
||||
LL | {"###);
|
||||
| ^ expected `'}'` in format string
|
||||
|
|
||||
= note: if you intended to print `{`, you can escape it using `{{`
|
||||
|
||||
error: invalid format string: expected `'}'` but string was terminated
|
||||
--> $DIR/format-string-error.rs:42:1
|
||||
|
|
||||
LL |
|
||||
| ^ expected `'}'` in format string
|
||||
|
|
||||
= note: if you intended to print `{`, you can escape it using `{{`
|
||||
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/format-string-error.rs:49:2
|
||||
|
|
||||
LL | }
|
||||
| ^ unmatched `}` in format string
|
||||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/format-string-error.rs:57:9
|
||||
|
|
||||
LL | }
|
||||
| ^ unmatched `}` in format string
|
||||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
error: format argument must be a string literal.
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/issue-11692-1.rs:12:12
|
||||
|
|
||||
LL | print!(test!());
|
||||
| ^^^^^^^
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | print!("{}", test!());
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2018 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
let x: u32 = 42;
|
||||
let y: f64 = 3.14;
|
||||
let z = "foo";
|
||||
let _ = concat!(x, y, z, "bar");
|
||||
//~^ ERROR expected a literal
|
||||
//~| NOTE only literals
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
error: expected a literal
|
||||
--> $DIR/bad-concat.rs:15:21
|
||||
|
|
||||
LL | let _ = concat!(x, y, z, "bar");
|
||||
| ^ ^ ^
|
||||
|
|
||||
= note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -9,5 +9,8 @@
|
|||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
println!(3 + 4); //~ ERROR expected a literal
|
||||
println!(3 + 4);
|
||||
//~^ ERROR format argument must be a string literal
|
||||
println!(3, 4);
|
||||
//~^ ERROR format argument must be a string literal
|
||||
}
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
error: expected a literal
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/bad_hello.rs:12:14
|
||||
|
|
||||
LL | println!(3 + 4); //~ ERROR expected a literal
|
||||
LL | println!(3 + 4);
|
||||
| ^^^^^
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | println!("{}", 3 + 4); //~ ERROR expected a literal
|
||||
| ^^^^^^^^^^^
|
||||
LL | println!("{}", 3 + 4);
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/bad_hello.rs:14:14
|
||||
|
|
||||
LL | println!(3, 4);
|
||||
| ^
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | println!("{} {}", 3, 4);
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -2,12 +2,13 @@ error: multiple unused formatting arguments
|
|||
--> $DIR/format-foreign.rs:12:30
|
||||
|
|
||||
LL | println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments
|
||||
| -------------------------^^^^^^^^--^^^^^^^--^-- multiple unused arguments in this statement
|
||||
| -------------- ^^^^^^^^ ^^^^^^^ ^
|
||||
| |
|
||||
| multiple missing formatting arguments
|
||||
|
|
||||
= help: `%.*3$s` should be written as `{:.2$}`
|
||||
= help: `%s` should be written as `{}`
|
||||
= note: printf formatting not supported; see the documentation for `std::fmt`
|
||||
= 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: argument never used
|
||||
--> $DIR/format-foreign.rs:13:29
|
||||
|
|
|
@ -2,24 +2,21 @@ error: multiple unused formatting arguments
|
|||
--> $DIR/format-unused-lables.rs:12:22
|
||||
|
|
||||
LL | println!("Test", 123, 456, 789);
|
||||
| -----------------^^^--^^^--^^^-- multiple unused arguments in this statement
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
| ------ ^^^ ^^^ ^^^
|
||||
| |
|
||||
| multiple missing formatting arguments
|
||||
|
||||
error: multiple unused formatting arguments
|
||||
--> $DIR/format-unused-lables.rs:16:9
|
||||
|
|
||||
LL | / println!("Test2",
|
||||
LL | | 123, //~ ERROR multiple unused formatting arguments
|
||||
| | ^^^
|
||||
LL | | 456,
|
||||
| | ^^^
|
||||
LL | | 789
|
||||
| | ^^^
|
||||
LL | | );
|
||||
| |______- multiple unused arguments in this statement
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
LL | println!("Test2",
|
||||
| ------- multiple missing formatting arguments
|
||||
LL | 123, //~ ERROR multiple unused formatting arguments
|
||||
| ^^^
|
||||
LL | 456,
|
||||
| ^^^
|
||||
LL | 789
|
||||
| ^^^
|
||||
|
||||
error: named argument never used
|
||||
--> $DIR/format-unused-lables.rs:21:35
|
||||
|
@ -30,18 +27,18 @@ LL | println!("Some stuff", UNUSED="args"); //~ ERROR named argument never u
|
|||
error: multiple unused formatting arguments
|
||||
--> $DIR/format-unused-lables.rs:24:9
|
||||
|
|
||||
LL | / println!("Some more $STUFF",
|
||||
LL | | "woo!", //~ ERROR multiple unused formatting arguments
|
||||
| | ^^^^^^
|
||||
LL | | STUFF=
|
||||
LL | | "things"
|
||||
| | ^^^^^^^^
|
||||
LL | | , UNUSED="args");
|
||||
| |_______________________^^^^^^_- multiple unused arguments in this statement
|
||||
LL | println!("Some more $STUFF",
|
||||
| ------------------ multiple missing formatting arguments
|
||||
LL | "woo!", //~ ERROR multiple unused formatting arguments
|
||||
| ^^^^^^
|
||||
LL | STUFF=
|
||||
LL | "things"
|
||||
| ^^^^^^^^
|
||||
LL | , UNUSED="args");
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: `$STUFF` should be written as `{STUFF}`
|
||||
= note: shell formatting not supported; see the documentation for `std::fmt`
|
||||
= 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 4 previous errors
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ LL | println!("Hello, World!");
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expanding `println! { "Hello, World!" }`
|
||||
= note: to `print ! ( concat ! ( "Hello, World!" , "/n" ) )`
|
||||
= note: expanding `print! { concat ! ( "Hello, World!" , "/n" ) }`
|
||||
= note: to `$crate :: io :: _print ( format_args ! ( concat ! ( "Hello, World!" , "/n" ) )
|
||||
)`
|
||||
= note: to `{
|
||||
# [ cfg ( not ( stage0 ) ) ] {
|
||||
( $crate :: io :: _print ( format_args_nl ! ( "Hello, World!" ) ) ) ; } # [
|
||||
cfg ( stage0 ) ] { print ! ( "{}/n" , format_args ! ( "Hello, World!" ) ) } }`
|
||||
|
||||
|
|
Loading…
Reference in New Issue