More descriptive argument placeholders

This commit is contained in:
Michael Goulet 2022-08-28 01:22:51 +00:00
parent 18b640aee5
commit 1256530643
9 changed files with 96 additions and 59 deletions

View File

@ -844,6 +844,12 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Vec<T> {
} }
} }
impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &[T] {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.try_map_id(|t| t.try_fold_with(folder)) self.try_map_id(|t| t.try_fold_with(folder))

View File

@ -76,16 +76,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
found: Ty<'tcx>, found: Ty<'tcx>,
can_satisfy: impl FnOnce(Ty<'tcx>) -> bool, can_satisfy: impl FnOnce(Ty<'tcx>) -> bool,
) -> 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; }; else { return false; };
if can_satisfy(output) { 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), 0 => ("".to_string(), Applicability::MachineApplicable),
1..=4 => ( 1..=4 => (
(0..num_inputs).map(|_| "_").collect::<Vec<_>>().join(", "), inputs
Applicability::MachineApplicable, .iter()
.map(|ty| {
if ty.is_suggestable(self.tcx, false) {
format!("/* {ty} */")
} else {
"".to_string()
}
})
.collect::<Vec<_>>()
.join(", "),
Applicability::HasPlaceholders,
), ),
_ => ("...".to_string(), Applicability::HasPlaceholders), _ => ("/* ... */".to_string(), Applicability::HasPlaceholders),
}; };
let msg = match def_id_or_name { let msg = match def_id_or_name {
@ -137,19 +147,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self, &self,
expr: &Expr<'_>, expr: &Expr<'_>,
found: Ty<'tcx>, found: Ty<'tcx>,
) -> Option<(DefIdOrName, Ty<'tcx>, usize)> { ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> {
// Autoderef is useful here because sometimes we box callables, etc. // 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, _)| { let Some((def_id_or_name, output, inputs)) = self.autoderef(expr.span, found).silence_errors().find_map(|(found, _)| {
match *found.kind() { match *found.kind() {
ty::FnPtr(fn_sig) => 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, _) => { ty::FnDef(def_id, _) => {
let fn_sig = found.fn_sig(self.tcx); 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) => { ty::Closure(def_id, substs) => {
let fn_sig = substs.as_closure().sig(); 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) => { ty::Opaque(def_id, substs) => {
self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| { 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(( Some((
DefIdOrName::DefId(def_id), DefIdOrName::DefId(def_id),
pred.kind().rebind(proj.term.ty().unwrap()), pred.kind().rebind(proj.term.ty().unwrap()),
args.len(), pred.kind().rebind(args.as_slice()),
)) ))
} else { } else {
None None
@ -178,7 +188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(( Some((
DefIdOrName::Name("trait object"), DefIdOrName::Name("trait object"),
pred.rebind(proj.term.ty().unwrap()), pred.rebind(proj.term.ty().unwrap()),
args.len(), pred.rebind(args.as_slice()),
)) ))
} else { } else {
None None
@ -197,7 +207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(( Some((
DefIdOrName::DefId(def_id), DefIdOrName::DefId(def_id),
pred.kind().rebind(proj.term.ty().unwrap()), pred.kind().rebind(proj.term.ty().unwrap()),
args.len(), pred.kind().rebind(args.as_slice()),
)) ))
} else { } else {
None None
@ -209,6 +219,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}) else { return None; }; }) else { return None; };
let output = self.replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, output); 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 // We don't want to register any extra obligations, which should be
// implied by wf, but also because that would possibly result in // 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>, rhs_ty: Ty<'tcx>,
can_satisfy: impl FnOnce(Ty<'tcx>, Ty<'tcx>) -> bool, can_satisfy: impl FnOnce(Ty<'tcx>, Ty<'tcx>) -> bool,
) -> 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; }; 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; }; else { return false; };
if can_satisfy(lhs_output_ty, rhs_output_ty) { if can_satisfy(lhs_output_ty, rhs_output_ty) {
let mut sugg = vec![]; let mut sugg = vec![];
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
for (expr, num_inputs) in [(lhs_expr, num_lhs_inputs), (rhs_expr, num_rhs_inputs)] { for (expr, inputs) in [(lhs_expr, lhs_inputs), (rhs_expr, rhs_inputs)] {
let (sugg_call, this_applicability) = match num_inputs { let (sugg_call, this_applicability) = match inputs.len() {
0 => ("".to_string(), Applicability::MachineApplicable), 0 => ("".to_string(), Applicability::MachineApplicable),
1..=4 => ( 1..=4 => (
(0..num_inputs).map(|_| "_").collect::<Vec<_>>().join(", "), inputs
Applicability::MachineApplicable, .iter()
.map(|ty| {
if ty.is_suggestable(self.tcx, false) {
format!("/* {ty} */")
} else {
"/* value */".to_string()
}
})
.collect::<Vec<_>>()
.join(", "),
Applicability::HasPlaceholders,
), ),
_ => ("...".to_string(), Applicability::HasPlaceholders), _ => ("/* ... */".to_string(), Applicability::HasPlaceholders),
}; };
applicability = applicability.max(this_applicability); applicability = applicability.max(this_applicability);

View File

@ -8,8 +8,8 @@ LL | if foo == y {}
| |
help: use parentheses to call this function help: use parentheses to call this function
| |
LL | if foo(_) == y {} LL | if foo(/* &i32 */) == y {}
| +++ | ++++++++++++
error: aborting due to previous error error: aborting due to previous error

View File

@ -10,8 +10,8 @@ LL | let _: () = Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>;
found struct `Box<dyn FnOnce(isize)>` found struct `Box<dyn FnOnce(isize)>`
help: use parentheses to call this trait object help: use parentheses to call this trait object
| |
LL | let _: () = (Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>)(_); LL | let _: () = (Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>)(/* isize */);
| + ++++ | + ++++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:10:17 --> $DIR/fn-trait-formatting.rs:10:17
@ -25,8 +25,8 @@ LL | let _: () = Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>
found struct `Box<dyn Fn(isize, isize)>` found struct `Box<dyn Fn(isize, isize)>`
help: use parentheses to call this trait object help: use parentheses to call this trait object
| |
LL | let _: () = (Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>)(_, _); LL | let _: () = (Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>)(/* isize */, /* isize */);
| + +++++++ | + +++++++++++++++++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:14:17 --> $DIR/fn-trait-formatting.rs:14:17

View File

@ -13,8 +13,8 @@ LL | fn test() -> Foo { Foo }
found fn item `fn(u32) -> Foo {Foo}` found fn item `fn(u32) -> Foo {Foo}`
help: use parentheses to instantiate this tuple struct 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 error: aborting due to previous error

View File

@ -30,8 +30,8 @@ LL | bar > 13;
| |
help: use parentheses to call this function help: use parentheses to call this function
| |
LL | bar(_) > 13; LL | bar(/* i64 */) > 13;
| +++ | +++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-59488.rs:18:11 --> $DIR/issue-59488.rs:18:11

View File

@ -329,8 +329,8 @@ LL | let _: Z = Z::Fn;
found fn item `fn(u8) -> Z {Z::Fn}` found fn item `fn(u8) -> Z {Z::Fn}`
help: use parentheses to instantiate this tuple variant 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` error[E0618]: expected function, found enum variant `Z::Unit`
--> $DIR/privacy-enum-ctor.rs:31:17 --> $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}` found fn item `fn(u8) -> E {E::Fn}`
help: use parentheses to instantiate this tuple variant 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` error[E0618]: expected function, found enum variant `m::E::Unit`
--> $DIR/privacy-enum-ctor.rs:47:16 --> $DIR/privacy-enum-ctor.rs:47:16
@ -399,8 +399,8 @@ LL | let _: E = E::Fn;
found fn item `fn(u8) -> E {E::Fn}` found fn item `fn(u8) -> E {E::Fn}`
help: use parentheses to instantiate this tuple variant 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` error[E0618]: expected function, found enum variant `E::Unit`
--> $DIR/privacy-enum-ctor.rs:55:16 --> $DIR/privacy-enum-ctor.rs:55:16

View File

@ -33,8 +33,8 @@ LL | let _: usize = foo;
found fn item `fn(usize, usize) -> usize {foo}` found fn item `fn(usize, usize) -> usize {foo}`
help: use parentheses to call this function help: use parentheses to call this function
| |
LL | let _: usize = foo(_, _); LL | let _: usize = foo(/* usize */, /* usize */);
| ++++++ | ++++++++++++++++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:30:16 --> $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}` found fn item `fn(usize, usize) -> S {S}`
help: use parentheses to instantiate this tuple struct help: use parentheses to instantiate this tuple struct
| |
LL | let _: S = S(_, _); LL | let _: S = S(/* usize */, /* usize */);
| ++++++ | ++++++++++++++++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:31:20 --> $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}` found fn item `fn(usize, usize) -> usize {<_ as T>::baz}`
help: use parentheses to call this associated function help: use parentheses to call this associated function
| |
LL | let _: usize = T::baz(_, _); LL | let _: usize = T::baz(/* usize */, /* usize */);
| ++++++ | ++++++++++++++++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:34:20 --> $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}` found fn item `fn(usize) -> usize {<_ as T>::bat}`
help: use parentheses to call this associated function help: use parentheses to call this associated function
| |
LL | let _: usize = T::bat(_); LL | let _: usize = T::bat(/* usize */);
| +++ | +++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:35:16 --> $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}` found fn item `fn(usize) -> E {E::A}`
help: use parentheses to instantiate this tuple variant help: use parentheses to instantiate this tuple variant
| |
LL | let _: E = E::A(_); LL | let _: E = E::A(/* usize */);
| +++ | +++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:37:20 --> $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 {<X as T>::baz}` found fn item `fn(usize, usize) -> usize {<X as T>::baz}`
help: use parentheses to call this associated function help: use parentheses to call this associated function
| |
LL | let _: usize = X::baz(_, _); LL | let _: usize = X::baz(/* usize */, /* usize */);
| ++++++ | ++++++++++++++++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:38:20 --> $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 {<X as T>::bat}` found fn item `fn(usize) -> usize {<X as T>::bat}`
help: use parentheses to call this associated function help: use parentheses to call this associated function
| |
LL | let _: usize = X::bat(_); LL | let _: usize = X::bat(/* usize */);
| +++ | +++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:39:20 --> $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 {<X as T>::bax}` found fn item `fn(usize) -> usize {<X as T>::bax}`
help: use parentheses to call this associated function help: use parentheses to call this associated function
| |
LL | let _: usize = X::bax(_); LL | let _: usize = X::bax(/* usize */);
| +++ | +++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:40:20 --> $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 {<X as T>::bach}` found fn item `fn(usize) -> usize {<X as T>::bach}`
help: use parentheses to call this associated function help: use parentheses to call this associated function
| |
LL | let _: usize = X::bach(_); LL | let _: usize = X::bach(/* usize */);
| +++ | +++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:41:20 --> $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 {<X as T>::ban}` found fn item `for<'r> fn(&'r X) -> usize {<X as T>::ban}`
help: use parentheses to call this associated function help: use parentheses to call this associated function
| |
LL | let _: usize = X::ban(_); LL | let _: usize = X::ban(/* &X */);
| +++ | ++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:42:20 --> $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 {<X as T>::bal}` found fn item `for<'r> fn(&'r X) -> usize {<X as T>::bal}`
help: use parentheses to call this associated function 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` error[E0615]: attempted to take value of method `ban` on type `X`
--> $DIR/fn-or-tuple-struct-without-args.rs:43:22 --> $DIR/fn-or-tuple-struct-without-args.rs:43:22

View File

@ -6,8 +6,8 @@ LL | thing.bar.0;
| |
help: use parentheses to instantiate this tuple struct help: use parentheses to instantiate this tuple struct
| |
LL | (thing.bar)(_, _).0; LL | (thing.bar)(/* char */, /* u16 */).0;
| + +++++++ | + ++++++++++++++++++++++++
error: aborting due to previous error error: aborting due to previous error