Skip to content

Commit 2fbd692

Browse files
committed
When possible, suggest fn call
1 parent 5976e0e commit 2fbd692

File tree

8 files changed

+64
-32
lines changed

8 files changed

+64
-32
lines changed

src/librustc/traits/chalk_fulfill.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
8181
.map(|obligation| FulfillmentError {
8282
obligation: obligation.goal.clone(),
8383
code: FulfillmentErrorCode::CodeAmbiguity,
84+
points_at_arg_span: false,
8485
})
8586
.collect();
8687
Err(errors)
@@ -129,6 +130,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
129130
code: FulfillmentErrorCode::CodeSelectionError(
130131
SelectionError::Unimplemented
131132
),
133+
points_at_arg_span: false,
132134
}),
133135
}
134136
} else {
@@ -142,6 +144,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
142144
code: FulfillmentErrorCode::CodeSelectionError(
143145
SelectionError::Unimplemented
144146
),
147+
points_at_arg_span: false,
145148
})
146149
}
147150
}

src/librustc/traits/error_reporting.rs

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
119119

120120
// returns if `cond` not occurring implies that `error` does not occur - i.e., that
121121
// `error` occurring implies that `cond` occurs.
122-
fn error_implies(&self,
123-
cond: &ty::Predicate<'tcx>,
124-
error: &ty::Predicate<'tcx>)
125-
-> bool
126-
{
122+
fn error_implies(
123+
&self,
124+
cond: &ty::Predicate<'tcx>,
125+
error: &ty::Predicate<'tcx>,
126+
) -> bool {
127127
if cond == error {
128128
return true
129129
}
@@ -155,13 +155,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
155155
false
156156
}
157157

158-
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>,
159-
body_id: Option<hir::BodyId>,
160-
fallback_has_occurred: bool) {
158+
fn report_fulfillment_error(
159+
&self,
160+
error: &FulfillmentError<'tcx>,
161+
body_id: Option<hir::BodyId>,
162+
fallback_has_occurred: bool,
163+
) {
161164
debug!("report_fulfillment_errors({:?})", error);
162165
match error.code {
163-
FulfillmentErrorCode::CodeSelectionError(ref e) => {
164-
self.report_selection_error(&error.obligation, e, fallback_has_occurred);
166+
FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
167+
self.report_selection_error(
168+
&error.obligation,
169+
selection_error,
170+
fallback_has_occurred,
171+
error.points_at_arg_span,
172+
);
165173
}
166174
FulfillmentErrorCode::CodeProjectionError(ref e) => {
167175
self.report_projection_error(&error.obligation, e);
@@ -170,19 +178,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
170178
self.maybe_report_ambiguity(&error.obligation, body_id);
171179
}
172180
FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
173-
self.report_mismatched_types(&error.obligation.cause,
174-
expected_found.expected,
175-
expected_found.found,
176-
err.clone())
177-
.emit();
181+
self.report_mismatched_types(
182+
&error.obligation.cause,
183+
expected_found.expected,
184+
expected_found.found,
185+
err.clone(),
186+
).emit();
178187
}
179188
}
180189
}
181190

182-
fn report_projection_error(&self,
183-
obligation: &PredicateObligation<'tcx>,
184-
error: &MismatchedProjectionTypes<'tcx>)
185-
{
191+
fn report_projection_error(
192+
&self,
193+
obligation: &PredicateObligation<'tcx>,
194+
error: &MismatchedProjectionTypes<'tcx>,
195+
) {
186196
let predicate =
187197
self.resolve_vars_if_possible(&obligation.predicate);
188198

@@ -603,6 +613,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
603613
obligation: &PredicateObligation<'tcx>,
604614
error: &SelectionError<'tcx>,
605615
fallback_has_occurred: bool,
616+
points_at_arg: bool,
606617
) {
607618
let span = obligation.cause.span;
608619

@@ -690,7 +701,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
690701
}
691702

692703
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
693-
self.suggest_fn_call(&obligation, &mut err, &trait_ref);
704+
self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
694705
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
695706
self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
696707

@@ -963,6 +974,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
963974
obligation: &PredicateObligation<'tcx>,
964975
err: &mut DiagnosticBuilder<'tcx>,
965976
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
977+
points_at_arg: bool,
966978
) {
967979
let self_ty = trait_ref.self_ty();
968980
match self_ty.sty {
@@ -991,15 +1003,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
9911003
..
9921004
})) = self.tcx.hir().get_if_local(def_id) {
9931005
let body = self.tcx.hir().body(*body_id);
994-
err.help(&format!(
995-
"use parentheses to call the function: `{}({})`",
1006+
let msg = "use parentheses to call the function";
1007+
let snippet = format!(
1008+
"{}({})",
9961009
ident,
9971010
body.params.iter()
9981011
.map(|arg| match &arg.pat.node {
9991012
hir::PatKind::Binding(_, _, ident, None)
10001013
if ident.name != kw::SelfLower => ident.to_string(),
10011014
_ => "_".to_string(),
1002-
}).collect::<Vec<_>>().join(", ")));
1015+
}).collect::<Vec<_>>().join(", "),
1016+
);
1017+
if points_at_arg {
1018+
err.span_suggestion(
1019+
obligation.cause.span,
1020+
msg,
1021+
snippet,
1022+
Applicability::HasPlaceholders,
1023+
);
1024+
} else {
1025+
err.help(&format!("{}: `{}`", msg, snippet));
1026+
}
10031027
}
10041028
}
10051029
_ => {}

src/librustc/traits/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,8 @@ EnumTypeFoldableImpl! {
484484

485485
pub struct FulfillmentError<'tcx> {
486486
pub obligation: PredicateObligation<'tcx>,
487-
pub code: FulfillmentErrorCode<'tcx>
487+
pub code: FulfillmentErrorCode<'tcx>,
488+
pub points_at_arg_span: bool,
488489
}
489490

490491
#[derive(Clone)]
@@ -1183,7 +1184,7 @@ impl<'tcx> FulfillmentError<'tcx> {
11831184
code: FulfillmentErrorCode<'tcx>)
11841185
-> FulfillmentError<'tcx>
11851186
{
1186-
FulfillmentError { obligation: obligation, code: code }
1187+
FulfillmentError { obligation: obligation, code: code, points_at_arg_span: false }
11871188
}
11881189
}
11891190

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
19991999
),
20002000
&traits::SelectionError::Unimplemented,
20012001
false,
2002+
false,
20022003
);
20032004
}
20042005
}

src/librustc_typeck/check/coercion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
617617

618618
// Object safety violations or miscellaneous.
619619
Err(err) => {
620-
self.report_selection_error(&obligation, &err, false);
620+
self.report_selection_error(&obligation, &err, false, false);
621621
// Treat this like an obligation and follow through
622622
// with the unsizing - the lack of a coercion should
623623
// be silent, as it causes a type mismatch later.

src/librustc_typeck/check/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3396,6 +3396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
33963396
}
33973397
if referenced_in.len() == 1 {
33983398
error.obligation.cause.span = args[referenced_in[0]].span;
3399+
error.points_at_arg_span = true;
33993400
}
34003401
}
34013402
}

src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ LL | fn bar(f: impl Future<Output=()>) {}
55
| --------------------------------- required by `bar`
66
...
77
LL | bar(foo);
8-
| ^^^ the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}`
9-
|
10-
= help: use parentheses to call the function: `foo()`
8+
| ^^^
9+
| |
10+
| the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}`
11+
| help: use parentheses to call the function: `foo()`
1112

1213
error: aborting due to previous error
1314

src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ LL | fn bar(f: impl T<O=()>) {}
55
| ----------------------- required by `bar`
66
...
77
LL | bar(foo);
8-
| ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
9-
|
10-
= help: use parentheses to call the function: `foo()`
8+
| ^^^
9+
| |
10+
| the trait `T` is not implemented for `fn() -> impl T {foo}`
11+
| help: use parentheses to call the function: `foo()`
1112

1213
error: aborting due to previous error
1314

0 commit comments

Comments
 (0)