From 778ce62482a3fd7db41f5c9354bbbe3fe5e13537 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Tue, 18 Feb 2014 18:33:32 -0800 Subject: [PATCH] format_args: allow omission of format string A default format string of Poly {:?} is generated to match the number of passed arguments. This propagates to all fmt macros, such as println!, debug!, format!, write!, etc. Example: println!("{:?}", value); => println!(value); fixes #12015 --- src/libsyntax/ext/format.rs | 34 ++++++++++++++++++++++++++++------ src/test/run-pass/ifmt.rs | 5 +++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 01d348595b88c..c0d0e732debbf 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -782,6 +782,20 @@ pub fn expand_args(ecx: &mut ExtCtxt, sp: Span, } } +/// Try to match a string literal, and if not found, emit a note. No big deal. +fn try_expr_literal(cx: &ExtCtxt, expr: @ast::Expr, note_msg: &str) + -> Option<~str> { + + match expr.node { + ast::ExprLit(l) => match l.node { + ast::LitStr(ref s, _) => return Some(s.get().to_owned()), + _ => cx.span_note(l.span, note_msg) + }, + _ => cx.span_note(expr.span, note_msg) + } + None +} + /// Take the various parts of `format_args!(extra, efmt, args..., /// name=names...)` and construct the appropriate formatting /// expression. @@ -807,14 +821,22 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, // Be sure to recursively expand macros just in case the format string uses // a macro to build the format expression. let expr = cx.ecx.expand_expr(efmt); - let fmt = match expr_to_str(cx.ecx, - expr, - "format argument must be a string literal.") { - Some((fmt, _)) => fmt, - None => return efmt + let fmt = match try_expr_literal(cx.ecx, + expr, + "format string literal missing, using default") { + Some(fmt) => fmt, + None => { + // push arg back into args lists + cx.args.unshift(expr); + cx.arg_types.unshift(None); + let mut parts = ~[]; + let form = ~"{:?}"; + parts.grow(cx.args.len(), &form); + parts.connect(" ") + } }; - let mut parser = parse::Parser::new(fmt.get()); + let mut parser = parse::Parser::new(fmt); loop { match parser.next() { Some(piece) => { diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index 09188b77ad8ae..28898c1413aef 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -48,6 +48,11 @@ pub fn main() { t!(format!("hello"), "hello"); t!(format!("hello \\{"), "hello {"); + // No format string uses default poly formatters + t!(format!(1), "1"); + t!(format!(1, 2), "1 2"); + t!(format!(1, "foo", 2, true), "1 \"foo\" 2 true"); + // default formatters should work t!(format!("{}", 1i), "1"); t!(format!("{}", 1i8), "1");