When possible, suggest fn call
This commit is contained in:
parent
5976e0eecf
commit
2fbd6927a5
8 changed files with 64 additions and 32 deletions
|
|
@ -81,6 +81,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||
.map(|obligation| FulfillmentError {
|
||||
obligation: obligation.goal.clone(),
|
||||
code: FulfillmentErrorCode::CodeAmbiguity,
|
||||
points_at_arg_span: false,
|
||||
})
|
||||
.collect();
|
||||
Err(errors)
|
||||
|
|
@ -129,6 +130,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||
code: FulfillmentErrorCode::CodeSelectionError(
|
||||
SelectionError::Unimplemented
|
||||
),
|
||||
points_at_arg_span: false,
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
|
|
@ -142,6 +144,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||
code: FulfillmentErrorCode::CodeSelectionError(
|
||||
SelectionError::Unimplemented
|
||||
),
|
||||
points_at_arg_span: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,11 +119,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
|
||||
// returns if `cond` not occurring implies that `error` does not occur - i.e., that
|
||||
// `error` occurring implies that `cond` occurs.
|
||||
fn error_implies(&self,
|
||||
cond: &ty::Predicate<'tcx>,
|
||||
error: &ty::Predicate<'tcx>)
|
||||
-> bool
|
||||
{
|
||||
fn error_implies(
|
||||
&self,
|
||||
cond: &ty::Predicate<'tcx>,
|
||||
error: &ty::Predicate<'tcx>,
|
||||
) -> bool {
|
||||
if cond == error {
|
||||
return true
|
||||
}
|
||||
|
|
@ -155,13 +155,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
false
|
||||
}
|
||||
|
||||
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>,
|
||||
body_id: Option<hir::BodyId>,
|
||||
fallback_has_occurred: bool) {
|
||||
fn report_fulfillment_error(
|
||||
&self,
|
||||
error: &FulfillmentError<'tcx>,
|
||||
body_id: Option<hir::BodyId>,
|
||||
fallback_has_occurred: bool,
|
||||
) {
|
||||
debug!("report_fulfillment_errors({:?})", error);
|
||||
match error.code {
|
||||
FulfillmentErrorCode::CodeSelectionError(ref e) => {
|
||||
self.report_selection_error(&error.obligation, e, fallback_has_occurred);
|
||||
FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
|
||||
self.report_selection_error(
|
||||
&error.obligation,
|
||||
selection_error,
|
||||
fallback_has_occurred,
|
||||
error.points_at_arg_span,
|
||||
);
|
||||
}
|
||||
FulfillmentErrorCode::CodeProjectionError(ref e) => {
|
||||
self.report_projection_error(&error.obligation, e);
|
||||
|
|
@ -170,19 +178,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
self.maybe_report_ambiguity(&error.obligation, body_id);
|
||||
}
|
||||
FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
|
||||
self.report_mismatched_types(&error.obligation.cause,
|
||||
expected_found.expected,
|
||||
expected_found.found,
|
||||
err.clone())
|
||||
.emit();
|
||||
self.report_mismatched_types(
|
||||
&error.obligation.cause,
|
||||
expected_found.expected,
|
||||
expected_found.found,
|
||||
err.clone(),
|
||||
).emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn report_projection_error(&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &MismatchedProjectionTypes<'tcx>)
|
||||
{
|
||||
fn report_projection_error(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &MismatchedProjectionTypes<'tcx>,
|
||||
) {
|
||||
let predicate =
|
||||
self.resolve_vars_if_possible(&obligation.predicate);
|
||||
|
||||
|
|
@ -603,6 +613,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &SelectionError<'tcx>,
|
||||
fallback_has_occurred: bool,
|
||||
points_at_arg: bool,
|
||||
) {
|
||||
let span = obligation.cause.span;
|
||||
|
||||
|
|
@ -690,7 +701,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
|
||||
self.suggest_fn_call(&obligation, &mut err, &trait_ref);
|
||||
self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
|
||||
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
|
||||
self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
|
||||
|
||||
|
|
@ -963,6 +974,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'tcx>,
|
||||
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
|
||||
points_at_arg: bool,
|
||||
) {
|
||||
let self_ty = trait_ref.self_ty();
|
||||
match self_ty.sty {
|
||||
|
|
@ -991,15 +1003,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
..
|
||||
})) = self.tcx.hir().get_if_local(def_id) {
|
||||
let body = self.tcx.hir().body(*body_id);
|
||||
err.help(&format!(
|
||||
"use parentheses to call the function: `{}({})`",
|
||||
let msg = "use parentheses to call the function";
|
||||
let snippet = format!(
|
||||
"{}({})",
|
||||
ident,
|
||||
body.params.iter()
|
||||
.map(|arg| match &arg.pat.node {
|
||||
hir::PatKind::Binding(_, _, ident, None)
|
||||
if ident.name != kw::SelfLower => ident.to_string(),
|
||||
_ => "_".to_string(),
|
||||
}).collect::<Vec<_>>().join(", ")));
|
||||
}).collect::<Vec<_>>().join(", "),
|
||||
);
|
||||
if points_at_arg {
|
||||
err.span_suggestion(
|
||||
obligation.cause.span,
|
||||
msg,
|
||||
snippet,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
} else {
|
||||
err.help(&format!("{}: `{}`", msg, snippet));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -484,7 +484,8 @@ EnumTypeFoldableImpl! {
|
|||
|
||||
pub struct FulfillmentError<'tcx> {
|
||||
pub obligation: PredicateObligation<'tcx>,
|
||||
pub code: FulfillmentErrorCode<'tcx>
|
||||
pub code: FulfillmentErrorCode<'tcx>,
|
||||
pub points_at_arg_span: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -1183,7 +1184,7 @@ impl<'tcx> FulfillmentError<'tcx> {
|
|||
code: FulfillmentErrorCode<'tcx>)
|
||||
-> FulfillmentError<'tcx>
|
||||
{
|
||||
FulfillmentError { obligation: obligation, code: code }
|
||||
FulfillmentError { obligation: obligation, code: code, points_at_arg_span: false }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1999,6 +1999,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
),
|
||||
&traits::SelectionError::Unimplemented,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -617,7 +617,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
|
||||
// Object safety violations or miscellaneous.
|
||||
Err(err) => {
|
||||
self.report_selection_error(&obligation, &err, false);
|
||||
self.report_selection_error(&obligation, &err, false, false);
|
||||
// Treat this like an obligation and follow through
|
||||
// with the unsizing - the lack of a coercion should
|
||||
// be silent, as it causes a type mismatch later.
|
||||
|
|
|
|||
|
|
@ -3396,6 +3396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
if referenced_in.len() == 1 {
|
||||
error.obligation.cause.span = args[referenced_in[0]].span;
|
||||
error.points_at_arg_span = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ LL | fn bar(f: impl Future<Output=()>) {}
|
|||
| --------------------------------- required by `bar`
|
||||
...
|
||||
LL | bar(foo);
|
||||
| ^^^ the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}`
|
||||
|
|
||||
= help: use parentheses to call the function: `foo()`
|
||||
| ^^^
|
||||
| |
|
||||
| the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}`
|
||||
| help: use parentheses to call the function: `foo()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ LL | fn bar(f: impl T<O=()>) {}
|
|||
| ----------------------- required by `bar`
|
||||
...
|
||||
LL | bar(foo);
|
||||
| ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
|
||||
|
|
||||
= help: use parentheses to call the function: `foo()`
|
||||
| ^^^
|
||||
| |
|
||||
| the trait `T` is not implemented for `fn() -> impl T {foo}`
|
||||
| help: use parentheses to call the function: `foo()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue