about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAmanieu d'Antras <amanieu@gmail.com>2020-06-11 01:27:48 +0100
committerAmanieu d'Antras <amanieu@gmail.com>2020-06-11 05:34:43 +0100
commitddacc671901359ef1cd95722af0ff23a7ca6e212 (patch)
tree9771981a3bb6951f2c0ba8def406124407b8fe5e
parent34bb6d0448a896b3d260f0858e3bccab63931141 (diff)
downloadrust-ddacc671901359ef1cd95722af0ff23a7ca6e212.tar.gz
rust-ddacc671901359ef1cd95722af0ff23a7ca6e212.zip
Add a suggestion to use unused asm arguments in comments
-rw-r--r--src/librustc_builtin_macros/asm.rs47
-rw-r--r--src/test/ui/asm/bad-template.rs2
-rw-r--r--src/test/ui/asm/bad-template.stderr18
-rw-r--r--src/test/ui/asm/parse-error.stderr2
4 files changed, 50 insertions, 19 deletions
diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs
index aabd5b5b5c3..f5b6e736fae 100644
--- a/src/librustc_builtin_macros/asm.rs
+++ b/src/librustc_builtin_macros/asm.rs
@@ -391,7 +391,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
         used[*pos] = true;
     }
 
-    let named_pos: FxHashSet<usize> = args.named_args.values().cloned().collect();
+    let named_pos: FxHashMap<usize, Symbol> =
+        args.named_args.iter().map(|(&sym, &idx)| (idx, sym)).collect();
     let mut arg_spans = parser.arg_places.iter().map(|span| template_span.from_inner(*span));
     let mut template = vec![];
     for piece in unverified_pieces {
@@ -405,7 +406,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
                 let operand_idx = match arg.position {
                     parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => {
                         if idx >= args.operands.len()
-                            || named_pos.contains(&idx)
+                            || named_pos.contains_key(&idx)
                             || args.reg_args.contains(&idx)
                         {
                             let msg = format!("invalid reference to argument at index {}", idx);
@@ -426,7 +427,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
                             };
                             err.note(&msg);
 
-                            if named_pos.contains(&idx) {
+                            if named_pos.contains_key(&idx) {
                                 err.span_label(args.operands[idx].1, "named argument");
                                 err.span_note(
                                     args.operands[idx].1,
@@ -480,27 +481,31 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
         }
     }
 
-    let operands = args.operands;
-    let unused_operands: Vec<_> = used
-        .into_iter()
-        .enumerate()
-        .filter(|&(_, used)| !used)
-        .map(|(idx, _)| {
-            if named_pos.contains(&idx) {
-                // named argument
-                (operands[idx].1, "named argument never used")
+    let mut unused_operands = vec![];
+    let mut help_str = String::new();
+    for (idx, used) in used.into_iter().enumerate() {
+        if !used {
+            let msg = if let Some(sym) = named_pos.get(&idx) {
+                help_str.push_str(&format!(" {{{}}}", sym));
+                "named argument never used"
             } else {
-                // positional argument
-                (operands[idx].1, "argument never used")
-            }
-        })
-        .collect();
+                help_str.push_str(&format!(" {{{}}}", idx));
+                "argument never used"
+            };
+            unused_operands.push((args.operands[idx].1, msg));
+        }
+    }
     match unused_operands.len() {
         0 => {}
         1 => {
             let (sp, msg) = unused_operands.into_iter().next().unwrap();
             let mut err = ecx.struct_span_err(sp, msg);
             err.span_label(sp, msg);
+            err.help(&format!(
+                "if this argument is intentionally unused, \
+                 consider using it in an asm comment: `\"/*{} */\"`",
+                help_str
+            ));
             err.emit();
         }
         _ => {
@@ -511,6 +516,11 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
             for (sp, msg) in unused_operands {
                 err.span_label(sp, msg);
             }
+            err.help(&format!(
+                "if these arguments are intentionally unused, \
+                 consider using them in an asm comment: `\"/*{} */\"`",
+                help_str
+            ));
             err.emit();
         }
     }
@@ -521,7 +531,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
         parser.line_spans.iter().map(|span| template_span.from_inner(*span)).collect()
     };
 
-    let inline_asm = ast::InlineAsm { template, operands, options: args.options, line_spans };
+    let inline_asm =
+        ast::InlineAsm { template, operands: args.operands, options: args.options, line_spans };
     P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
         kind: ast::ExprKind::InlineAsm(P(inline_asm)),
diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs
index 0b333eca1ab..21ce8c6236d 100644
--- a/src/test/ui/asm/bad-template.rs
+++ b/src/test/ui/asm/bad-template.rs
@@ -22,5 +22,7 @@ fn main() {
         //~^ ERROR invalid reference to argument at index 0
         asm!("{:foo}", in(reg) foo);
         //~^ ERROR asm template modifier must be a single character
+        asm!("", in(reg) 0, in(reg) 1);
+        //~^ ERROR multiple unused asm arguments
     }
 }
diff --git a/src/test/ui/asm/bad-template.stderr b/src/test/ui/asm/bad-template.stderr
index 2de76ef8241..1aea7467ed0 100644
--- a/src/test/ui/asm/bad-template.stderr
+++ b/src/test/ui/asm/bad-template.stderr
@@ -19,6 +19,8 @@ error: argument never used
    |
 LL |         asm!("{1}", in(reg) foo);
    |                     ^^^^^^^^^^^ argument never used
+   |
+   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
   --> $DIR/bad-template.rs:13:15
@@ -46,6 +48,8 @@ error: named argument never used
    |
 LL |         asm!("{}", a = in(reg) foo);
    |                    ^^^^^^^^^^^^^^^ named argument never used
+   |
+   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
   --> $DIR/bad-template.rs:18:15
@@ -60,6 +64,8 @@ error: named argument never used
    |
 LL |         asm!("{1}", a = in(reg) foo);
    |                     ^^^^^^^^^^^^^^^ named argument never used
+   |
+   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 0
   --> $DIR/bad-template.rs:21:15
@@ -82,5 +88,15 @@ error: asm template modifier must be a single character
 LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
-error: aborting due to 10 previous errors
+error: multiple unused asm arguments
+  --> $DIR/bad-template.rs:25:18
+   |
+LL |         asm!("", in(reg) 0, in(reg) 1);
+   |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
+   |                  |
+   |                  argument never used
+   |
+   = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr
index fa422f56bec..583a1057036 100644
--- a/src/test/ui/asm/parse-error.stderr
+++ b/src/test/ui/asm/parse-error.stderr
@@ -127,6 +127,8 @@ error: argument never used
    |
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                                    ^^^^^^^^^^^^^ argument never used
+   |
+   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
 error: explicit register arguments cannot have names
   --> $DIR/parse-error.rs:47:18