about summary refs log tree commit diff
path: root/src/libsyntax_ext
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-11-05 11:55:00 -0800
committerEsteban Küber <esteban@kuber.com.ar>2019-11-05 14:06:38 -0800
commit08b235b5bed1a53311da34fa12966cd42a2a5abe (patch)
tree2cbd042c2d9d566b1bc6d62d7b5d02e255d21b17 /src/libsyntax_ext
parent3a1b3b30c6cdd674049b144a3ced7b711de962b2 (diff)
downloadrust-08b235b5bed1a53311da34fa12966cd42a2a5abe.tar.gz
rust-08b235b5bed1a53311da34fa12966cd42a2a5abe.zip
Point at formatting descriptor string when it is invalid
When a formatting string contains an invalid descriptor, point at it
instead of the argument:

```
error: unknown format trait `foo`
  --> $DIR/ifmt-bad-arg.rs:86:17
   |
LL |     println!("{:foo}", 1);
   |                 ^^^
   |
   = note: the only appropriate formatting traits are:
           - ``, which uses the `Display` trait
           - `?`, which uses the `Debug` trait
           - `e`, which uses the `LowerExp` trait
           - `E`, which uses the `UpperExp` trait
           - `o`, which uses the `Octal` trait
           - `p`, which uses the `Pointer` trait
           - `b`, which uses the `Binary` trait
           - `x`, which uses the `LowerHex` trait
           - `X`, which uses the `UpperHex` trait
```
Diffstat (limited to 'src/libsyntax_ext')
-rw-r--r--src/libsyntax_ext/format.rs67
1 files changed, 34 insertions, 33 deletions
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 37310f46f7e..b8d053a2162 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -21,7 +21,7 @@ use std::collections::hash_map::Entry;
 
 #[derive(PartialEq)]
 enum ArgumentType {
-    Placeholder(String),
+    Placeholder(&'static str),
     Count,
 }
 
@@ -244,7 +244,36 @@ impl<'a, 'b> Context<'a, 'b> {
                     parse::ArgumentNamed(s) => Named(s),
                 };
 
-                let ty = Placeholder(arg.format.ty.to_string());
+                let ty = Placeholder(match &arg.format.ty[..] {
+                    "" => "Display",
+                    "?" => "Debug",
+                    "e" => "LowerExp",
+                    "E" => "UpperExp",
+                    "o" => "Octal",
+                    "p" => "Pointer",
+                    "b" => "Binary",
+                    "x" => "LowerHex",
+                    "X" => "UpperHex",
+                    _ => {
+                        let fmtsp = self.fmtsp;
+                        let mut err = self.ecx.struct_span_err(
+                            arg.format.ty_span.map(|sp| fmtsp.from_inner(sp)).unwrap_or(fmtsp),
+                            &format!("unknown format trait `{}`", arg.format.ty),
+                        );
+                        err.note("the only appropriate formatting traits are:\n\
+                                - ``, which uses the `Display` trait\n\
+                                - `?`, which uses the `Debug` trait\n\
+                                - `e`, which uses the `LowerExp` trait\n\
+                                - `E`, which uses the `UpperExp` trait\n\
+                                - `o`, which uses the `Octal` trait\n\
+                                - `p`, which uses the `Pointer` trait\n\
+                                - `b`, which uses the `Binary` trait\n\
+                                - `x`, which uses the `LowerHex` trait\n\
+                                - `X`, which uses the `UpperHex` trait");
+                        err.emit();
+                        "<invalid>"
+                    }
+                });
                 self.verify_arg_type(pos, ty);
                 self.curpiece += 1;
             }
@@ -588,6 +617,7 @@ impl<'a, 'b> Context<'a, 'b> {
                         width: parse::CountImplied,
                         width_span: None,
                         ty: arg.format.ty,
+                        ty_span: arg.format.ty_span,
                     },
                 };
 
@@ -759,37 +789,8 @@ impl<'a, 'b> Context<'a, 'b> {
         sp = ecx.with_def_site_ctxt(sp);
         let arg = ecx.expr_ident(sp, arg);
         let trait_ = match *ty {
-            Placeholder(ref tyname) => {
-                match &tyname[..] {
-                    "" => "Display",
-                    "?" => "Debug",
-                    "e" => "LowerExp",
-                    "E" => "UpperExp",
-                    "o" => "Octal",
-                    "p" => "Pointer",
-                    "b" => "Binary",
-                    "x" => "LowerHex",
-                    "X" => "UpperHex",
-                    _ => {
-                        let mut err = ecx.struct_span_err(
-                            sp,
-                            &format!("unknown format trait `{}`", *tyname),
-                        );
-                        err.note("the only appropriate formatting traits are:\n\
-                                  - ``, which uses the `Display` trait\n\
-                                  - `?`, which uses the `Debug` trait\n\
-                                  - `e`, which uses the `LowerExp` trait\n\
-                                  - `E`, which uses the `UpperExp` trait\n\
-                                  - `o`, which uses the `Octal` trait\n\
-                                  - `p`, which uses the `Pointer` trait\n\
-                                  - `b`, which uses the `Binary` trait\n\
-                                  - `x`, which uses the `LowerHex` trait\n\
-                                  - `X`, which uses the `UpperHex` trait");
-                        err.emit();
-                        return DummyResult::raw_expr(sp, true);
-                    }
-                }
-            }
+            Placeholder(trait_) if trait_ == "<invalid>" => return DummyResult::raw_expr(sp, true),
+            Placeholder(trait_) => trait_,
             Count => {
                 let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, sym::from_usize]);
                 return ecx.expr_call_global(macsp, path, vec![arg]);