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]> {
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))

View File

@ -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::<Vec<_>>().join(", "),
Applicability::MachineApplicable,
inputs
.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 {
@ -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<Ty<'tcx>>)> {
// 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::<Vec<_>>().join(", "),
Applicability::MachineApplicable,
inputs
.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);

View File

@ -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

View File

@ -10,8 +10,8 @@ LL | let _: () = Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>;
found struct `Box<dyn FnOnce(isize)>`
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
--> $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)>`
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
--> $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}`
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

View File

@ -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

View File

@ -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

View File

@ -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 {<X as T>::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 {<X as T>::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 {<X as T>::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 {<X as T>::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 {<X as T>::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 {<X as T>::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

View File

@ -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