diff options
author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-07-03 23:30:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-03 23:30:08 +0200 |
commit | 603130948b532b98862ddd504f3db57eb6f06eeb (patch) | |
tree | 74476d0040a51e88a4cba0e6b263b691f2eec82c /compiler | |
parent | 77fa597079d7854dedf45f8a86fcdf05668dc551 (diff) | |
parent | 9f32459c988dec799458f304bbc49ed5dc6ef772 (diff) |
Rollup merge of #127253 - chenyukang:yukang-fix-126246-fn-parameters-check, r=estebank
Fix incorrect suggestion for extra argument with a type error
Fixes #126246
I tried to fix it in the `find_errors` of ArgMatrix, but seems it's hard to avoid breaking some other test cases.
The root cause is we eliminate the first argument even with a type error at here:
https://github.com/rust-lang/rust/blob/6292b2af620dbd771ebb687c3a93c69ba8f97268/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs#L664
So the left argument is always treated as extra one.
But if there is already a type error, an error message will be generated firstly, which make this issue a trivial one.
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 26 |
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(), |