From 1256530643fdd4762de8de5a47041fc2cf700828 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 28 Aug 2022 01:22:51 +0000 Subject: [PATCH] More descriptive argument placeholders --- .../rustc_middle/src/ty/structural_impls.rs | 6 ++ .../src/check/fn_ctxt/suggestions.rs | 69 ++++++++++++++----- src/test/ui/binop/issue-77910-2.stderr | 4 +- src/test/ui/fn/fn-trait-formatting.stderr | 8 +-- src/test/ui/issues/issue-35241.stderr | 4 +- src/test/ui/issues/issue-59488.stderr | 4 +- src/test/ui/resolve/privacy-enum-ctor.stderr | 12 ++-- .../fn-or-tuple-struct-without-args.stderr | 44 ++++++------ .../ui/typeck/issue-87181/tuple-field.stderr | 4 +- 9 files changed, 96 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 7660a2f3af6..57555433f55 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -844,6 +844,12 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Vec { } } +impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &[T] { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|t| t.try_fold_with(folder)) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 96901b53303..d48bdbd7b6d 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -76,16 +76,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found: Ty<'tcx>, can_satisfy: impl FnOnce(Ty<'tcx>) -> bool, ) -> bool { - let Some((def_id_or_name, output, num_inputs)) = self.extract_callable_info(expr, found) + let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(expr, found) else { return false; }; if can_satisfy(output) { - let (sugg_call, mut applicability) = match num_inputs { + let (sugg_call, mut applicability) = match inputs.len() { 0 => ("".to_string(), Applicability::MachineApplicable), 1..=4 => ( - (0..num_inputs).map(|_| "_").collect::>().join(", "), - Applicability::MachineApplicable, + inputs + .iter() + .map(|ty| { + if ty.is_suggestable(self.tcx, false) { + format!("/* {ty} */") + } else { + "".to_string() + } + }) + .collect::>() + .join(", "), + Applicability::HasPlaceholders, ), - _ => ("...".to_string(), Applicability::HasPlaceholders), + _ => ("/* ... */".to_string(), Applicability::HasPlaceholders), }; let msg = match def_id_or_name { @@ -137,19 +147,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expr: &Expr<'_>, found: Ty<'tcx>, - ) -> Option<(DefIdOrName, Ty<'tcx>, usize)> { + ) -> Option<(DefIdOrName, Ty<'tcx>, Vec>)> { // Autoderef is useful here because sometimes we box callables, etc. let Some((def_id_or_name, output, inputs)) = self.autoderef(expr.span, found).silence_errors().find_map(|(found, _)| { match *found.kind() { ty::FnPtr(fn_sig) => - Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs().skip_binder().len())), + Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs())), ty::FnDef(def_id, _) => { let fn_sig = found.fn_sig(self.tcx); - Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().skip_binder().len())) + Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs())) } ty::Closure(def_id, substs) => { let fn_sig = substs.as_closure().sig(); - Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().skip_binder().len() - 1)) + Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..]))) } ty::Opaque(def_id, substs) => { self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| { @@ -161,7 +171,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(( DefIdOrName::DefId(def_id), pred.kind().rebind(proj.term.ty().unwrap()), - args.len(), + pred.kind().rebind(args.as_slice()), )) } else { None @@ -178,7 +188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(( DefIdOrName::Name("trait object"), pred.rebind(proj.term.ty().unwrap()), - args.len(), + pred.rebind(args.as_slice()), )) } else { None @@ -197,7 +207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(( DefIdOrName::DefId(def_id), pred.kind().rebind(proj.term.ty().unwrap()), - args.len(), + pred.kind().rebind(args.as_slice()), )) } else { None @@ -209,6 +219,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) else { return None; }; let output = self.replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, output); + let inputs = inputs + .skip_binder() + .iter() + .map(|ty| { + self.replace_bound_vars_with_fresh_vars( + expr.span, + infer::FnCall, + inputs.rebind(*ty), + ) + }) + .collect(); // We don't want to register any extra obligations, which should be // implied by wf, but also because that would possibly result in @@ -228,23 +249,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_ty: Ty<'tcx>, can_satisfy: impl FnOnce(Ty<'tcx>, Ty<'tcx>) -> bool, ) -> bool { - let Some((_, lhs_output_ty, num_lhs_inputs)) = self.extract_callable_info(lhs_expr, lhs_ty) + let Some((_, lhs_output_ty, lhs_inputs)) = self.extract_callable_info(lhs_expr, lhs_ty) else { return false; }; - let Some((_, rhs_output_ty, num_rhs_inputs)) = self.extract_callable_info(rhs_expr, rhs_ty) + let Some((_, rhs_output_ty, rhs_inputs)) = self.extract_callable_info(rhs_expr, rhs_ty) else { return false; }; if can_satisfy(lhs_output_ty, rhs_output_ty) { let mut sugg = vec![]; let mut applicability = Applicability::MachineApplicable; - for (expr, num_inputs) in [(lhs_expr, num_lhs_inputs), (rhs_expr, num_rhs_inputs)] { - let (sugg_call, this_applicability) = match num_inputs { + for (expr, inputs) in [(lhs_expr, lhs_inputs), (rhs_expr, rhs_inputs)] { + let (sugg_call, this_applicability) = match inputs.len() { 0 => ("".to_string(), Applicability::MachineApplicable), 1..=4 => ( - (0..num_inputs).map(|_| "_").collect::>().join(", "), - Applicability::MachineApplicable, + inputs + .iter() + .map(|ty| { + if ty.is_suggestable(self.tcx, false) { + format!("/* {ty} */") + } else { + "/* value */".to_string() + } + }) + .collect::>() + .join(", "), + Applicability::HasPlaceholders, ), - _ => ("...".to_string(), Applicability::HasPlaceholders), + _ => ("/* ... */".to_string(), Applicability::HasPlaceholders), }; applicability = applicability.max(this_applicability); diff --git a/src/test/ui/binop/issue-77910-2.stderr b/src/test/ui/binop/issue-77910-2.stderr index 74860a93f37..a334bd85625 100644 --- a/src/test/ui/binop/issue-77910-2.stderr +++ b/src/test/ui/binop/issue-77910-2.stderr @@ -8,8 +8,8 @@ LL | if foo == y {} | help: use parentheses to call this function | -LL | if foo(_) == y {} - | +++ +LL | if foo(/* &i32 */) == y {} + | ++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/fn/fn-trait-formatting.stderr b/src/test/ui/fn/fn-trait-formatting.stderr index 1d5e0a859a6..2a674d3c1d2 100644 --- a/src/test/ui/fn/fn-trait-formatting.stderr +++ b/src/test/ui/fn/fn-trait-formatting.stderr @@ -10,8 +10,8 @@ LL | let _: () = Box::new(|_: isize| {}) as Box; found struct `Box` help: use parentheses to call this trait object | -LL | let _: () = (Box::new(|_: isize| {}) as Box)(_); - | + ++++ +LL | let _: () = (Box::new(|_: isize| {}) as Box)(/* isize */); + | + ++++++++++++++ error[E0308]: mismatched types --> $DIR/fn-trait-formatting.rs:10:17 @@ -25,8 +25,8 @@ LL | let _: () = Box::new(|_: isize, isize| {}) as Box found struct `Box` help: use parentheses to call this trait object | -LL | let _: () = (Box::new(|_: isize, isize| {}) as Box)(_, _); - | + +++++++ +LL | let _: () = (Box::new(|_: isize, isize| {}) as Box)(/* isize */, /* isize */); + | + +++++++++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/fn-trait-formatting.rs:14:17 diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr index a66289a1cf8..9ee7654a088 100644 --- a/src/test/ui/issues/issue-35241.stderr +++ b/src/test/ui/issues/issue-35241.stderr @@ -13,8 +13,8 @@ LL | fn test() -> Foo { Foo } found fn item `fn(u32) -> Foo {Foo}` help: use parentheses to instantiate this tuple struct | -LL | fn test() -> Foo { Foo(_) } - | +++ +LL | fn test() -> Foo { Foo(/* u32 */) } + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index df681eb2489..e5368ddf1e5 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -30,8 +30,8 @@ LL | bar > 13; | help: use parentheses to call this function | -LL | bar(_) > 13; - | +++ +LL | bar(/* i64 */) > 13; + | +++++++++++ error[E0308]: mismatched types --> $DIR/issue-59488.rs:18:11 diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index f885ac2151d..7cf32775a33 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -329,8 +329,8 @@ LL | let _: Z = Z::Fn; found fn item `fn(u8) -> Z {Z::Fn}` help: use parentheses to instantiate this tuple variant | -LL | let _: Z = Z::Fn(_); - | +++ +LL | let _: Z = Z::Fn(/* u8 */); + | ++++++++++ error[E0618]: expected function, found enum variant `Z::Unit` --> $DIR/privacy-enum-ctor.rs:31:17 @@ -364,8 +364,8 @@ LL | let _: E = m::E::Fn; found fn item `fn(u8) -> E {E::Fn}` help: use parentheses to instantiate this tuple variant | -LL | let _: E = m::E::Fn(_); - | +++ +LL | let _: E = m::E::Fn(/* u8 */); + | ++++++++++ error[E0618]: expected function, found enum variant `m::E::Unit` --> $DIR/privacy-enum-ctor.rs:47:16 @@ -399,8 +399,8 @@ LL | let _: E = E::Fn; found fn item `fn(u8) -> E {E::Fn}` help: use parentheses to instantiate this tuple variant | -LL | let _: E = E::Fn(_); - | +++ +LL | let _: E = E::Fn(/* u8 */); + | ++++++++++ error[E0618]: expected function, found enum variant `E::Unit` --> $DIR/privacy-enum-ctor.rs:55:16 diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index ba710bfa746..3c7b895e337 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -33,8 +33,8 @@ LL | let _: usize = foo; found fn item `fn(usize, usize) -> usize {foo}` help: use parentheses to call this function | -LL | let _: usize = foo(_, _); - | ++++++ +LL | let _: usize = foo(/* usize */, /* usize */); + | ++++++++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:30:16 @@ -51,8 +51,8 @@ LL | let _: S = S; found fn item `fn(usize, usize) -> S {S}` help: use parentheses to instantiate this tuple struct | -LL | let _: S = S(_, _); - | ++++++ +LL | let _: S = S(/* usize */, /* usize */); + | ++++++++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:31:20 @@ -105,8 +105,8 @@ LL | let _: usize = T::baz; found fn item `fn(usize, usize) -> usize {<_ as T>::baz}` help: use parentheses to call this associated function | -LL | let _: usize = T::baz(_, _); - | ++++++ +LL | let _: usize = T::baz(/* usize */, /* usize */); + | ++++++++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:34:20 @@ -123,8 +123,8 @@ LL | let _: usize = T::bat; found fn item `fn(usize) -> usize {<_ as T>::bat}` help: use parentheses to call this associated function | -LL | let _: usize = T::bat(_); - | +++ +LL | let _: usize = T::bat(/* usize */); + | +++++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:35:16 @@ -141,8 +141,8 @@ LL | let _: E = E::A; found fn item `fn(usize) -> E {E::A}` help: use parentheses to instantiate this tuple variant | -LL | let _: E = E::A(_); - | +++ +LL | let _: E = E::A(/* usize */); + | +++++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:37:20 @@ -159,8 +159,8 @@ LL | let _: usize = X::baz; found fn item `fn(usize, usize) -> usize {::baz}` help: use parentheses to call this associated function | -LL | let _: usize = X::baz(_, _); - | ++++++ +LL | let _: usize = X::baz(/* usize */, /* usize */); + | ++++++++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:38:20 @@ -177,8 +177,8 @@ LL | let _: usize = X::bat; found fn item `fn(usize) -> usize {::bat}` help: use parentheses to call this associated function | -LL | let _: usize = X::bat(_); - | +++ +LL | let _: usize = X::bat(/* usize */); + | +++++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:39:20 @@ -195,8 +195,8 @@ LL | let _: usize = X::bax; found fn item `fn(usize) -> usize {::bax}` help: use parentheses to call this associated function | -LL | let _: usize = X::bax(_); - | +++ +LL | let _: usize = X::bax(/* usize */); + | +++++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:40:20 @@ -213,8 +213,8 @@ LL | let _: usize = X::bach; found fn item `fn(usize) -> usize {::bach}` help: use parentheses to call this associated function | -LL | let _: usize = X::bach(_); - | +++ +LL | let _: usize = X::bach(/* usize */); + | +++++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:41:20 @@ -231,8 +231,8 @@ LL | let _: usize = X::ban; found fn item `for<'r> fn(&'r X) -> usize {::ban}` help: use parentheses to call this associated function | -LL | let _: usize = X::ban(_); - | +++ +LL | let _: usize = X::ban(/* &X */); + | ++++++++++ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:42:20 @@ -249,8 +249,8 @@ LL | let _: usize = X::bal; found fn item `for<'r> fn(&'r X) -> usize {::bal}` help: use parentheses to call this associated function | -LL | let _: usize = X::bal(_); - | +++ +LL | let _: usize = X::bal(/* &X */); + | ++++++++++ error[E0615]: attempted to take value of method `ban` on type `X` --> $DIR/fn-or-tuple-struct-without-args.rs:43:22 diff --git a/src/test/ui/typeck/issue-87181/tuple-field.stderr b/src/test/ui/typeck/issue-87181/tuple-field.stderr index 0e43ace8933..c1ca26ee9af 100644 --- a/src/test/ui/typeck/issue-87181/tuple-field.stderr +++ b/src/test/ui/typeck/issue-87181/tuple-field.stderr @@ -6,8 +6,8 @@ LL | thing.bar.0; | help: use parentheses to instantiate this tuple struct | -LL | (thing.bar)(_, _).0; - | + +++++++ +LL | (thing.bar)(/* char */, /* u16 */).0; + | + ++++++++++++++++++++++++ error: aborting due to previous error