about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs50
-rw-r--r--tests/ui/argument-suggestions/issue-100478.stderr16
-rw-r--r--tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr12
3 files changed, 58 insertions, 20 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 36abd7c8555..b80a2af3100 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1589,26 +1589,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // e.g. `reuse HasSelf::method;` should suggest `reuse HasSelf::method($args);`.
                 full_call_span.shrink_to_hi()
             };
+
+            // Controls how the arguments should be listed in the suggestion.
+            enum ArgumentsFormatting {
+                SingleLine,
+                Multiline { fallback_indent: String, brace_indent: String },
+            }
+            let arguments_formatting = {
+                let mut provided_inputs = matched_inputs.iter().filter_map(|a| *a);
+                if let Some(brace_indent) = source_map.indentation_before(suggestion_span)
+                    && let Some(first_idx) = provided_inputs.by_ref().next()
+                    && let Some(last_idx) = provided_inputs.by_ref().next()
+                    && let (_, first_span) = provided_arg_tys[first_idx]
+                    && let (_, last_span) = provided_arg_tys[last_idx]
+                    && source_map.is_multiline(first_span.to(last_span))
+                    && let Some(fallback_indent) = source_map.indentation_before(first_span)
+                {
+                    ArgumentsFormatting::Multiline { fallback_indent, brace_indent }
+                } else {
+                    ArgumentsFormatting::SingleLine
+                }
+            };
+
             let mut suggestion = "(".to_owned();
             let mut needs_comma = false;
             for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
                 if needs_comma {
-                    suggestion += ", ";
-                } else {
-                    needs_comma = true;
+                    suggestion += ",";
+                }
+                match &arguments_formatting {
+                    ArgumentsFormatting::SingleLine if needs_comma => suggestion += " ",
+                    ArgumentsFormatting::SingleLine => {}
+                    ArgumentsFormatting::Multiline { .. } => suggestion += "\n",
                 }
-                let suggestion_text = if let Some(provided_idx) = provided_idx
+                needs_comma = true;
+                let (suggestion_span, suggestion_text) = if let Some(provided_idx) = provided_idx
                     && let (_, provided_span) = provided_arg_tys[*provided_idx]
                     && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
                 {
-                    arg_text
+                    (Some(provided_span), arg_text)
                 } else {
                     // Propose a placeholder of the correct type
                     let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
-                    ty_to_snippet(expected_ty, expected_idx)
+                    (None, ty_to_snippet(expected_ty, expected_idx))
                 };
+                if let ArgumentsFormatting::Multiline { fallback_indent, .. } =
+                    &arguments_formatting
+                {
+                    let indent = suggestion_span
+                        .and_then(|span| source_map.indentation_before(span))
+                        .unwrap_or_else(|| fallback_indent.clone());
+                    suggestion += &indent;
+                }
                 suggestion += &suggestion_text;
             }
+            if let ArgumentsFormatting::Multiline { brace_indent, .. } = arguments_formatting {
+                suggestion += ",\n";
+                suggestion += &brace_indent;
+            }
             suggestion += ")";
             err.span_suggestion_verbose(
                 suggestion_span,
diff --git a/tests/ui/argument-suggestions/issue-100478.stderr b/tests/ui/argument-suggestions/issue-100478.stderr
index 8889a0ab5df..81dbff2f000 100644
--- a/tests/ui/argument-suggestions/issue-100478.stderr
+++ b/tests/ui/argument-suggestions/issue-100478.stderr
@@ -75,12 +75,16 @@ LL | fn foo(p1: T1, p2: Arc<T2>, p3: T3, p4: Arc<T4>, p5: T5, p6: T6, p7: T7, p8
    |    ^^^         -----------
 help: provide the argument
    |
-LL -     foo(
-LL -
-LL -         p1, //p2,
-LL -         p3, p4, p5, p6, p7, p8,
-LL -     );
-LL +     foo(p1, /* Arc<T2> */, p3, p4, p5, p6, p7, p8);
+LL ~     foo(
+LL +         p1,
+LL +         /* Arc<T2> */,
+LL +         p3,
+LL +         p4,
+LL +         p5,
+LL +         p6,
+LL +         p7,
+LL +         p8,
+LL ~     );
    |
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr
index 494d9bf60a6..dda9b398a83 100644
--- a/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr
+++ b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr
@@ -99,14 +99,10 @@ LL | fn function_with_lots_of_arguments(a: i32, b: char, c: i32, d: i32, e: i32,
    |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^         -------
 help: provide the argument
    |
-LL -     function_with_lots_of_arguments(
-LL -         variable_name,
-LL -         variable_name,
-LL -         variable_name,
-LL -         variable_name,
-LL -         variable_name,
-LL -     );
-LL +     function_with_lots_of_arguments(variable_name, /* char */, variable_name, variable_name, variable_name, variable_name);
+LL |     function_with_lots_of_arguments(
+LL |         variable_name,
+LL ~         /* char */,
+LL ~         variable_name,
    |
 
 error: aborting due to 6 previous errors