Skip to content

Followups for method call error change #96155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1584,9 +1584,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Variable(ty::error::ExpectedFound<Ty<'a>>),
Fixed(&'static str),
}
let (expected_found, exp_found, is_simple_error) = match values {
None => (None, Mismatch::Fixed("type"), false),
let (expected_found, exp_found, is_simple_error, values) = match values {
None => (None, Mismatch::Fixed("type"), false, None),
Some(values) => {
let values = self.resolve_vars_if_possible(values);
let (is_simple_error, exp_found) = match values {
ValuePairs::Terms(infer::ExpectedFound {
expected: ty::Term::Ty(expected),
Expand Down Expand Up @@ -1614,7 +1615,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
return;
}
};
(vals, exp_found, is_simple_error)
(vals, exp_found, is_simple_error, Some(values))
}
};

Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_typeck/src/check/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub fn check_legal_trait_for_method_call(

enum CallStep<'tcx> {
Builtin(Ty<'tcx>),
DeferredClosure(ty::FnSig<'tcx>),
DeferredClosure(DefId, ty::FnSig<'tcx>),
/// E.g., enum variant constructors.
Overloaded(MethodCallee<'tcx>),
}
Expand Down Expand Up @@ -107,8 +107,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.confirm_builtin_call(call_expr, callee_expr, callee_ty, arg_exprs, expected)
}

Some(CallStep::DeferredClosure(fn_sig)) => {
self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig)
Some(CallStep::DeferredClosure(def_id, fn_sig)) => {
self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, def_id, fn_sig)
}

Some(CallStep::Overloaded(method_callee)) => {
Expand Down Expand Up @@ -171,7 +171,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
closure_substs: substs,
},
);
return Some(CallStep::DeferredClosure(closure_sig));
return Some(CallStep::DeferredClosure(def_id, closure_sig));
}
}

Expand Down Expand Up @@ -533,6 +533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
call_expr: &'tcx hir::Expr<'tcx>,
arg_exprs: &'tcx [hir::Expr<'tcx>],
expected: Expectation<'tcx>,
closure_def_id: DefId,
fn_sig: ty::FnSig<'tcx>,
) -> Ty<'tcx> {
// `fn_sig` is the *signature* of the closure being called. We
Expand All @@ -555,7 +556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs,
fn_sig.c_variadic,
TupleArgumentsFlag::TupleArguments,
None,
Some(closure_def_id),
);

fn_sig.output()
Expand Down
142 changes: 63 additions & 79 deletions compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use rustc_infer::infer::TypeTrace;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::symbol::Ident;
use rustc_span::{self, Span};
Expand Down Expand Up @@ -394,6 +394,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
break 'errors;
}

self.set_tainted_by_errors();

// The algorithm here is inspired by levenshtein distance and longest common subsequence.
// We'll try to detect 4 different types of mistakes:
// - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
Expand Down Expand Up @@ -502,6 +504,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
TupleMatchFound::Single => {
let expected_ty = expected_input_tys[0];
let provided_ty = final_arg_types[0].map(|ty| ty.0).unwrap();
let expected_ty = self.resolve_vars_if_possible(expected_ty);
let provided_ty = self.resolve_vars_if_possible(provided_ty);
let cause = &self.misc(provided_args[0].span);
let compatibility = demand_compatible(0, &mut final_arg_types);
let type_error = match compatibility {
Expand All @@ -523,24 +527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("arguments to this {} are incorrect", call_name),
);
// Call out where the function is defined
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();

let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.map(|id| tcx.hir().body(id).params)
.flatten();

for param in params {
spans.push_span_label(param.span, String::new());
}

let def_kind = tcx.def_kind(def_id);
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
}
label_fn_like(tcx, &mut err, fn_def_id);
err.emit();
break 'errors;
}
Expand All @@ -558,24 +545,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
DiagnosticId::Error(err_code.to_owned()),
);
// Call out where the function is defined
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();

let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.map(|id| tcx.hir().body(id).params)
.flatten();

for param in params {
spans.push_span_label(param.span, String::new());
}

let def_kind = tcx.def_kind(def_id);
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
}
label_fn_like(tcx, &mut err, fn_def_id);
err.multipart_suggestion(
"use parentheses to construct a tuple",
vec![(start, '('.to_string()), (end, ')'.to_string())],
Expand All @@ -597,13 +567,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
let expected_ty = expected_input_tys[*input_idx];
let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap();
let expected_ty = self.resolve_vars_if_possible(expected_ty);
let provided_ty = self.resolve_vars_if_possible(provided_ty);
let cause = &self.misc(provided_args[*input_idx].span);
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
let mut err = self.report_and_explain_type_error(trace, error);
self.emit_coerce_suggestions(
&mut err,
&provided_args[*input_idx],
final_arg_types[*input_idx].map(|ty| ty.0).unwrap(),
provided_ty,
final_arg_types[*input_idx].map(|ty| ty.1).unwrap(),
None,
None,
Expand All @@ -613,24 +585,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("arguments to this {} are incorrect", call_name),
);
// Call out where the function is defined
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();

let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.map(|id| tcx.hir().body(id).params)
.flatten();

for param in params {
spans.push_span_label(param.span, String::new());
}

let def_kind = tcx.def_kind(def_id);
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
}
label_fn_like(tcx, &mut err, fn_def_id);
err.emit();
break 'errors;
}
Expand Down Expand Up @@ -678,12 +633,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match error {
Error::Invalid(input_idx, compatibility) => {
let expected_ty = expected_input_tys[input_idx];
let provided_ty = final_arg_types
.get(input_idx)
.and_then(|x| x.as_ref())
.map(|ty| ty.0)
.unwrap_or(tcx.ty_error());
let expected_ty = self.resolve_vars_if_possible(expected_ty);
let provided_ty = self.resolve_vars_if_possible(provided_ty);
if let Compatibility::Incompatible(error) = &compatibility {
let provided_ty = final_arg_types
.get(input_idx)
.and_then(|x| x.as_ref())
.map(|ty| ty.0)
.unwrap_or(tcx.ty_error());
let cause = &self.misc(
provided_args.get(input_idx).map(|i| i.span).unwrap_or(call_span),
);
Expand Down Expand Up @@ -948,24 +905,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

// Call out where the function is defined
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();

let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.flat_map(|id| tcx.hir().body(id).params)
;

for param in params {
spans.push_span_label(param.span, String::new());
}

let def_kind = tcx.def_kind(def_id);
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
}
label_fn_like(tcx, &mut err, fn_def_id);

// And add a suggestion block for all of the parameters
let suggestion_text = match suggestion_text {
Expand Down Expand Up @@ -1790,3 +1730,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}

fn label_fn_like<'tcx>(
tcx: TyCtxt<'tcx>,
err: &mut rustc_errors::DiagnosticBuilder<'tcx, rustc_errors::ErrorGuaranteed>,
def_id: Option<DefId>,
) {
let Some(def_id) = def_id else {
return;
};

if let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();

let params = tcx
.hir()
.get_if_local(def_id)
.and_then(|node| node.body_id())
.into_iter()
.map(|id| tcx.hir().body(id).params)
.flatten();

for param in params {
spans.push_span_label(param.span, String::new());
}

let def_kind = tcx.def_kind(def_id);
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
} else {
match tcx.hir().get_if_local(def_id) {
Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_, _, _, span, ..),
..
})) => {
let spans: MultiSpan = (*span).into();

// Note: We don't point to param spans here because they overlap
// with the closure span itself

err.span_note(spans, "closure defined here");
}
_ => {}
}
}
}
3 changes: 3 additions & 0 deletions src/test/ui/argument-suggestions/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ fn main() {
missing(); //~ ERROR this function takes
swapped("", 1); //~ ERROR arguments to this function are incorrect
permuted(Y {}, Z {}, X {}); //~ ERROR arguments to this function are incorrect

let closure = |x| x;
closure(); //~ ERROR this function takes
}
22 changes: 19 additions & 3 deletions src/test/ui/argument-suggestions/basic.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,23 @@ help: reorder these arguments
LL | permuted(X {}, Y {}, Z {});
| ~~~~~~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 5 previous errors
error[E0057]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/basic.rs:27:5
|
LL | closure();
| ^^^^^^^-- an argument is missing
|
note: closure defined here
--> $DIR/basic.rs:26:19
|
LL | let closure = |x| x;
| ^^^
help: provide the argument
|
LL | closure({_});
| ~~~~~~~~~~~~

error: aborting due to 6 previous errors

Some errors have detailed explanations: E0061, E0308.
For more information about an error, try `rustc --explain E0061`.
Some errors have detailed explanations: E0057, E0061, E0308.
For more information about an error, try `rustc --explain E0057`.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ note: expected this to be `Option<T>`
|
LL | type Item = T;
| ^
= note: expected enum `Option<T>`
found type `T`
= note: expected enum `Option<T>`
found type parameter `T`
note: required by a bound in `is_iterator_of`
--> $DIR/associated-types-issue-20346.rs:15:34
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | foo(());
| ^^^ lifetime mismatch
|
= note: expected reference `&'a ()`
found type `&()`
found reference `&()`
note: the lifetime requirement is introduced here
--> $DIR/higher-ranked-projection.rs:15:33
|
Expand Down
27 changes: 16 additions & 11 deletions src/test/ui/async-await/generator-desc.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ LL | fun(one(), two());
| |
| arguments to this function are incorrect
|
note: while checking the return type of the `async fn`
--> $DIR/generator-desc.rs:5:16
|
LL | async fn one() {}
| ^ checked the `Output` of this `async fn`, expected opaque type
note: while checking the return type of the `async fn`
--> $DIR/generator-desc.rs:6:16
|
LL | async fn two() {}
| ^ checked the `Output` of this `async fn`, found opaque type
= note: expected type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
= note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types
note: function defined here
Expand All @@ -43,26 +48,26 @@ error[E0308]: mismatched types
--> $DIR/generator-desc.rs:14:26
|
LL | fun((async || {})(), (async || {})());
| --- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
| |
| --- -- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
| | |
| | the expected `async` closure body
| arguments to this function are incorrect
|
::: $SRC_DIR/core/src/future/mod.rs:LL:COL
|
LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
| ------------------------------- the found opaque type
| -------------------------------
| |
| the expected opaque type
| the found opaque type
|
= note: expected type `impl Future<Output = ()>` (`async` closure body)
found opaque type `impl Future<Output = ()>` (`async` closure body)
= note: expected opaque type `impl Future<Output = ()>` (`async` closure body)
found opaque type `impl Future<Output = ()>` (`async` closure body)
note: function defined here
--> $DIR/generator-desc.rs:8:4
|
LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
| ^^^ ----- -----
help: consider `await`ing on the `Future`
|
LL | fun((async || {})(), (async || {})().await);
| ++++++

error: aborting due to 3 previous errors

Expand Down
Loading