Skip to content

Commit ed7ce52

Browse files
Rollup merge of #96646 - estebank:issue-96638, r=jackh726
Mitigate impact of subtle invalid call suggestion logic There's some subtle interaction between inferred expressions being passed as an argument to fn calls with fewer than expected arguments. To avoid the ICE, I'm changing indexing operations with `.get(idx)`, but the underlying logic still needs to be audited as it was written with the assumption that `final_arg_types` and `provided_args` have the right length. Address #96638.
2 parents c161dcc + 7790b6e commit ed7ce52

File tree

3 files changed

+48
-12
lines changed

3 files changed

+48
-12
lines changed

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+20-12
Original file line numberDiff line numberDiff line change
@@ -429,9 +429,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
429429
errors.drain_filter(|error| {
430430
let Error::Invalid(input_idx, Compatibility::Incompatible(error)) = error else { return false };
431431
let expected_ty = expected_input_tys[*input_idx];
432-
let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap();
432+
let Some(Some((provided_ty, _))) = final_arg_types.get(*input_idx) else { return false };
433433
let cause = &self.misc(provided_args[*input_idx].span);
434-
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
434+
let trace = TypeTrace::types(cause, true, expected_ty, *provided_ty);
435435
if let Some(e) = error {
436436
if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
437437
self.report_and_explain_type_error(trace, e).emit();
@@ -679,8 +679,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
679679
Error::Invalid(input_idx, compatibility) => {
680680
let expected_ty = expected_input_tys[input_idx];
681681
if let Compatibility::Incompatible(error) = &compatibility {
682-
let provided_ty = final_arg_types[input_idx].map(|ty| ty.0).unwrap();
683-
let cause = &self.misc(provided_args[input_idx].span);
682+
let provided_ty = final_arg_types
683+
.get(input_idx)
684+
.and_then(|x| x.as_ref())
685+
.map(|ty| ty.0)
686+
.unwrap_or(tcx.ty_error());
687+
let cause = &self.misc(
688+
provided_args.get(input_idx).map(|i| i.span).unwrap_or(call_span),
689+
);
684690
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
685691
if let Some(e) = error {
686692
self.note_type_err(
@@ -695,14 +701,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
695701
}
696702
}
697703

698-
self.emit_coerce_suggestions(
699-
&mut err,
700-
&provided_args[input_idx],
701-
final_arg_types[input_idx].map(|ty| ty.0).unwrap(),
702-
final_arg_types[input_idx].map(|ty| ty.1).unwrap(),
703-
None,
704-
None,
705-
);
704+
if let Some(expr) = provided_args.get(input_idx) {
705+
self.emit_coerce_suggestions(
706+
&mut err,
707+
&expr,
708+
final_arg_types[input_idx].map(|ty| ty.0).unwrap(),
709+
final_arg_types[input_idx].map(|ty| ty.1).unwrap(),
710+
None,
711+
None,
712+
);
713+
}
706714
}
707715
Error::Extra(arg_idx) => {
708716
let arg_type = if let Some((_, ty)) = final_arg_types[arg_idx] {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn f(_: usize, _: &usize, _: usize) {}
2+
3+
fn arg<T>() -> T { todo!() }
4+
5+
fn main() {
6+
let x = arg(); // `x` must be inferred
7+
// The reference on `&x` is important to reproduce the ICE
8+
f(&x, ""); //~ ERROR this function takes 3 arguments but 2 arguments were supplied
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0061]: this function takes 3 arguments but 2 arguments were supplied
2+
--> $DIR/issue-96638.rs:8:5
3+
|
4+
LL | f(&x, "");
5+
| ^ -- an argument of type `usize` is missing
6+
|
7+
note: function defined here
8+
--> $DIR/issue-96638.rs:1:4
9+
|
10+
LL | fn f(_: usize, _: &usize, _: usize) {}
11+
| ^ -------- --------- --------
12+
help: provide the argument
13+
|
14+
LL | f({usize}, &x, {usize});
15+
| ~~~~~~~~~~~~~~~~~~~~~~~
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0061`.

0 commit comments

Comments
 (0)