diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs index aabd5b5b5c31b..f5b6e736fae99 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 = args.named_args.values().cloned().collect(); + let named_pos: FxHashMap = + 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 { 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, sp: Span, args: AsmArgs) -> P = 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, sp: Span, args: AsmArgs) -> P $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 fa422f56bece5..583a10570360b 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