summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs26
1 files changed, 26 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 4bab25c9727..56dff080867 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -951,6 +951,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return err.emit();
}
+ // Special case, we found an extra argument is provided, which is very common in practice.
+ // but there is a obviously better removing suggestion compared to the current one,
+ // try to find the argument with Error type, if we removed it all the types will become good,
+ // then we will replace the current suggestion.
+ if let [Error::Extra(provided_idx)] = &errors[..] {
+ let remove_idx_is_perfect = |idx: usize| -> bool {
+ let removed_arg_tys = provided_arg_tys
+ .iter()
+ .enumerate()
+ .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
+ .collect::<IndexVec<ProvidedIdx, _>>();
+ std::iter::zip(formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
+ |((expected_ty, _), (provided_ty, _))| {
+ !provided_ty.references_error()
+ && self.can_coerce(*provided_ty, *expected_ty)
+ },
+ )
+ };
+
+ if !remove_idx_is_perfect(provided_idx.as_usize()) {
+ if let Some(i) = (0..provided_args.len()).find(|&i| remove_idx_is_perfect(i)) {
+ errors = vec![Error::Extra(ProvidedIdx::from_usize(i))];
+ }
+ }
+ }
+
let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
struct_span_code_err!(
self.dcx(),