From 0b20096eff0e12690e63be97647b50383402e57c Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 18 Jun 2023 18:44:14 +0800 Subject: [PATCH 1/2] sort the errors from arguments checking so that suggestions are handled properly --- .../src/fn_ctxt/arg_matrix.rs | 13 ++++++--- tests/ui/argument-suggestions/issue-112507.rs | 12 +++++++++ .../argument-suggestions/issue-112507.stderr | 27 +++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 tests/ui/argument-suggestions/issue-112507.rs create mode 100644 tests/ui/argument-suggestions/issue-112507.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs index d45e3d395e430..e535d244c895e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs @@ -1,7 +1,7 @@ -use std::cmp; - +use core::cmp::Ordering; use rustc_index::IndexVec; use rustc_middle::ty::error::TypeError; +use std::cmp; rustc_index::newtype_index! { #[debug_format = "ExpectedIdx({})"] @@ -177,7 +177,7 @@ impl<'tcx> ArgMatrix<'tcx> { // If an argument is unsatisfied, and the input in its position is useless // then the most likely explanation is that we just got the types wrong (true, true, true, true) => return Some(Issue::Invalid(i)), - // Otherwise, if an input is useless, then indicate that this is an extra argument + // Otherwise, if an input is useless then indicate that this is an extra input (true, _, true, _) => return Some(Issue::Extra(i)), // Otherwise, if an argument is unsatisfiable, indicate that it's missing (_, true, _, true) => return Some(Issue::Missing(i)), @@ -376,6 +376,13 @@ impl<'tcx> ArgMatrix<'tcx> { }; } + // sort errors with same type by the order they appear in the source + // so that suggestion will be handled properly, see #112507 + errors.sort_by(|a, b| match (a, b) { + (Error::Missing(i), Error::Missing(j)) => i.cmp(j), + (Error::Extra(i), Error::Extra(j)) => i.cmp(j), + _ => Ordering::Equal, + }); return (errors, matched_inputs); } } diff --git a/tests/ui/argument-suggestions/issue-112507.rs b/tests/ui/argument-suggestions/issue-112507.rs new file mode 100644 index 0000000000000..61743c59a4aab --- /dev/null +++ b/tests/ui/argument-suggestions/issue-112507.rs @@ -0,0 +1,12 @@ +pub enum Value { + Float(Option), +} + +fn main() { + let _a = Value::Float( //~ ERROR this enum variant takes 1 argument but 4 arguments were supplied + 0, + None, + None, + 0, + ); +} diff --git a/tests/ui/argument-suggestions/issue-112507.stderr b/tests/ui/argument-suggestions/issue-112507.stderr new file mode 100644 index 0000000000000..dfb47e010e49f --- /dev/null +++ b/tests/ui/argument-suggestions/issue-112507.stderr @@ -0,0 +1,27 @@ +error[E0061]: this enum variant takes 1 argument but 4 arguments were supplied + --> $DIR/issue-112507.rs:6:14 + | +LL | let _a = Value::Float( + | ^^^^^^^^^^^^ +LL | 0, + | - unexpected argument of type `{integer}` +LL | None, +LL | None, + | ---- unexpected argument of type `Option<_>` +LL | 0, + | - unexpected argument of type `{integer}` + | +note: tuple variant defined here + --> $DIR/issue-112507.rs:2:5 + | +LL | Float(Option), + | ^^^^^ +help: remove the extra arguments + | +LL ~ , +LL ~ None); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. From aba1cf159ffc53c72149703bf4f7cf072c3dd65f Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 19 Jun 2023 11:03:48 +0800 Subject: [PATCH 2/2] fix sort --- .../src/fn_ctxt/arg_matrix.rs | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs index e535d244c895e..7aadb95d9393e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs @@ -34,14 +34,14 @@ enum Issue { Permutation(Vec>), } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub(crate) enum Compatibility<'tcx> { Compatible, Incompatible(Option>), } /// Similar to `Issue`, but contains some extra information -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub(crate) enum Error<'tcx> { /// The provided argument is the invalid type for the expected input Invalid(ProvidedIdx, ExpectedIdx, Compatibility<'tcx>), @@ -55,6 +55,34 @@ pub(crate) enum Error<'tcx> { Permutation(Vec<(ExpectedIdx, ProvidedIdx)>), } +impl Ord for Error<'_> { + fn cmp(&self, other: &Self) -> Ordering { + let key = |error: &Error<'_>| -> usize { + match error { + Error::Invalid(..) => 0, + Error::Extra(_) => 1, + Error::Missing(_) => 2, + Error::Swap(..) => 3, + Error::Permutation(..) => 4, + } + }; + match (self, other) { + (Error::Invalid(a, _, _), Error::Invalid(b, _, _)) => a.cmp(b), + (Error::Extra(a), Error::Extra(b)) => a.cmp(b), + (Error::Missing(a), Error::Missing(b)) => a.cmp(b), + (Error::Swap(a, b, ..), Error::Swap(c, d, ..)) => a.cmp(c).then(b.cmp(d)), + (Error::Permutation(a), Error::Permutation(b)) => a.cmp(b), + _ => key(self).cmp(&key(other)), + } + } +} + +impl PartialOrd for Error<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + pub(crate) struct ArgMatrix<'tcx> { /// Maps the indices in the `compatibility_matrix` rows to the indices of /// the *user provided* inputs @@ -378,11 +406,7 @@ impl<'tcx> ArgMatrix<'tcx> { // sort errors with same type by the order they appear in the source // so that suggestion will be handled properly, see #112507 - errors.sort_by(|a, b| match (a, b) { - (Error::Missing(i), Error::Missing(j)) => i.cmp(j), - (Error::Extra(i), Error::Extra(j)) => i.cmp(j), - _ => Ordering::Equal, - }); + errors.sort(); return (errors, matched_inputs); } }