Skip to content

Commit 1922f0b

Browse files
Rollup merge of rust-lang#97557 - compiler-errors:arg-mismatch-mini, r=jackh726
Fix indices and remove some unwraps in arg mismatch algorithm This is a more conservative fix than rust-lang#97542, addressing some indices which were used incorectly and unwraps which are bound to panic (e.g. when the provided and expected arg counts differ). Beta nominating this as it's quite easy to cause ICEs -- I wrote a fuzzer and found hundreds of examples of ICEs. cc `@jackh726` as author of rust-lang#92364, and `@estebank` as reviewer of that PR. fixes rust-lang#97484 r? `@jackh726` this should be _much_ easier to review than the other PR 😅
2 parents 263d868 + 4b26d41 commit 1922f0b

File tree

7 files changed

+95
-47
lines changed

7 files changed

+95
-47
lines changed

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

+25-18
Original file line numberDiff line numberDiff line change
@@ -445,16 +445,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
445445
let found_errors = !errors.is_empty();
446446

447447
errors.drain_filter(|error| {
448-
let Error::Invalid(input_idx, arg_idx, Compatibility::Incompatible(error)) = error else { return false };
448+
let Error::Invalid(input_idx, arg_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
449449
let expected_ty = expected_input_tys[*arg_idx];
450-
let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap();
450+
let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap_or_else(|| tcx.ty_error());
451451
let cause = &self.misc(provided_args[*input_idx].span);
452452
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
453-
if let Some(e) = error {
454-
if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
455-
self.report_and_explain_type_error(trace, e).emit();
456-
return true;
457-
}
453+
if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
454+
self.report_and_explain_type_error(trace, e).emit();
455+
return true;
458456
}
459457
false
460458
});
@@ -585,7 +583,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
585583
)) = errors.iter().next()
586584
{
587585
let expected_ty = expected_input_tys[*arg_idx];
588-
let provided_ty = final_arg_types[*arg_idx].map(|ty| ty.0).unwrap();
586+
let provided_ty = final_arg_types[*input_idx]
587+
.map(|ty| ty.0)
588+
.unwrap_or_else(|| tcx.ty_error());
589589
let expected_ty = self.resolve_vars_if_possible(expected_ty);
590590
let provided_ty = self.resolve_vars_if_possible(provided_ty);
591591
let cause = &self.misc(provided_args[*input_idx].span);
@@ -595,7 +595,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
595595
&mut err,
596596
&provided_args[*input_idx],
597597
provided_ty,
598-
final_arg_types[*input_idx].map(|ty| ty.1).unwrap(),
598+
final_arg_types[*input_idx]
599+
.map(|ty| ty.1)
600+
.unwrap_or_else(|| tcx.ty_error()),
599601
None,
600602
None,
601603
);
@@ -652,7 +654,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
652654
match error {
653655
Error::Invalid(input_idx, arg_idx, compatibility) => {
654656
let expected_ty = expected_input_tys[arg_idx];
655-
let provided_ty = final_arg_types[input_idx].map(|ty| ty.0).unwrap();
657+
let provided_ty = final_arg_types[input_idx]
658+
.map(|ty| ty.0)
659+
.unwrap_or_else(|| tcx.ty_error());
656660
let expected_ty = self.resolve_vars_if_possible(expected_ty);
657661
let provided_ty = self.resolve_vars_if_possible(provided_ty);
658662
if let Compatibility::Incompatible(error) = &compatibility {
@@ -674,8 +678,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
674678
self.emit_coerce_suggestions(
675679
&mut err,
676680
&provided_args[input_idx],
677-
final_arg_types[input_idx].map(|ty| ty.0).unwrap(),
678-
final_arg_types[input_idx].map(|ty| ty.1).unwrap(),
681+
provided_ty,
682+
// FIXME(compiler-errors): expected_ty?
683+
final_arg_types[input_idx]
684+
.map(|ty| ty.1)
685+
.unwrap_or_else(|| tcx.ty_error()),
679686
None,
680687
None,
681688
);
@@ -860,7 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
860867
let first_expected_ty =
861868
self.resolve_vars_if_possible(expected_input_tys[arg_idx]);
862869
let first_provided_ty = if let Some((ty, _)) = final_arg_types[input_idx] {
863-
format!(",found `{}`", ty)
870+
format!(", found `{}`", ty)
864871
} else {
865872
String::new()
866873
};
@@ -872,7 +879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
872879
self.resolve_vars_if_possible(expected_input_tys[other_arg_idx]);
873880
let other_provided_ty =
874881
if let Some((ty, _)) = final_arg_types[other_input_idx] {
875-
format!(",found `{}`", ty)
882+
format!(", found `{}`", ty)
876883
} else {
877884
String::new()
878885
};
@@ -888,14 +895,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
888895
Error::Permutation(args) => {
889896
for (dst_arg, dest_input) in args {
890897
let expected_ty =
891-
self.resolve_vars_if_possible(expected_input_tys[dest_input]);
892-
let provided_ty = if let Some((ty, _)) = final_arg_types[dst_arg] {
893-
format!(",found `{}`", ty)
898+
self.resolve_vars_if_possible(expected_input_tys[dst_arg]);
899+
let provided_ty = if let Some((ty, _)) = final_arg_types[dest_input] {
900+
format!(", found `{}`", ty)
894901
} else {
895902
String::new()
896903
};
897904
labels.push((
898-
provided_args[dst_arg].span,
905+
provided_args[dest_input].span,
899906
format!("expected `{}`{}", expected_ty, provided_ty),
900907
));
901908
}

src/test/ui/argument-suggestions/basic.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ error[E0308]: arguments to this function are incorrect
4848
--> $DIR/basic.rs:23:5
4949
|
5050
LL | swapped("", 1);
51-
| ^^^^^^^ -- - expected `&str`,found `{integer}`
51+
| ^^^^^^^ -- - expected `&str`, found `{integer}`
5252
| |
53-
| expected `u32`,found `&'static str`
53+
| expected `u32`, found `&'static str`
5454
|
5555
note: function defined here
5656
--> $DIR/basic.rs:16:4
@@ -66,10 +66,10 @@ error[E0308]: arguments to this function are incorrect
6666
--> $DIR/basic.rs:24:5
6767
|
6868
LL | permuted(Y {}, Z {}, X {});
69-
| ^^^^^^^^ ---- ---- ---- expected `Z`,found `X`
69+
| ^^^^^^^^ ---- ---- ---- expected `Z`, found `X`
7070
| | |
71-
| | expected `Y`,found `Z`
72-
| expected `X`,found `Y`
71+
| | expected `Y`, found `Z`
72+
| expected `X`, found `Y`
7373
|
7474
note: function defined here
7575
--> $DIR/basic.rs:17:4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
struct A;
2+
struct B;
3+
struct C;
4+
struct D;
5+
struct E;
6+
struct F;
7+
struct G;
8+
9+
fn foo(a: &A, d: D, e: &E, g: G) {}
10+
11+
fn main() {
12+
foo(&&A, B, C, D, E, F, G);
13+
//~^ ERROR this function takes 4 arguments but 7 arguments were supplied
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0061]: this function takes 4 arguments but 7 arguments were supplied
2+
--> $DIR/issue-97484.rs:12:5
3+
|
4+
LL | foo(&&A, B, C, D, E, F, G);
5+
| ^^^ - - - argument unexpected
6+
| | |
7+
| | argument of type `&E` unexpected
8+
| argument of type `D` unexpected
9+
|
10+
note: function defined here
11+
--> $DIR/issue-97484.rs:9:4
12+
|
13+
LL | fn foo(a: &A, d: D, e: &E, g: G) {}
14+
| ^^^ ----- ---- ----- ----
15+
help: consider removing the ``
16+
|
17+
LL - foo(&&A, B, C, D, E, F, G);
18+
LL + foo(&&A, B, C, D, E, F, G);
19+
|
20+
help: remove the extra arguments
21+
|
22+
LL | foo(&&A, D, {&E}, G);
23+
| ~~~~~~~~~~~~~~~~~~~~
24+
25+
error: aborting due to previous error
26+
27+
For more information about this error, try `rustc --explain E0061`.

src/test/ui/argument-suggestions/mixed_cases.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ error[E0308]: arguments to this function are incorrect
7676
--> $DIR/mixed_cases.rs:20:3
7777
|
7878
LL | three_args("", X {}, 1);
79-
| ^^^^^^^^^^ -- ---- - expected `&str`,found `{integer}`
79+
| ^^^^^^^^^^ -- ---- - expected `&str`, found `{integer}`
8080
| | |
8181
| | expected `f32`, found struct `X`
82-
| expected `i32`,found `&'static str`
82+
| expected `i32`, found `&'static str`
8383
|
8484
note: function defined here
8585
--> $DIR/mixed_cases.rs:6:4
@@ -98,8 +98,8 @@ LL | three_args("", 1);
9898
| ^^^^^^^^^^ -- -
9999
| | |
100100
| | an argument of type `f32` is missing
101-
| | expected `&str`,found `{integer}`
102-
| expected `i32`,found `&'static str`
101+
| | expected `&str`, found `{integer}`
102+
| expected `i32`, found `&'static str`
103103
|
104104
note: function defined here
105105
--> $DIR/mixed_cases.rs:6:4

src/test/ui/argument-suggestions/permuted_arguments.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ error[E0308]: arguments to this function are incorrect
22
--> $DIR/permuted_arguments.rs:10:3
33
|
44
LL | three_args(1.0, "", 1);
5-
| ^^^^^^^^^^ --- -- - expected `&str`,found `{integer}`
5+
| ^^^^^^^^^^ --- -- - expected `&str`, found `{integer}`
66
| | |
7-
| | expected `f32`,found `&'static str`
8-
| expected `i32`,found `{float}`
7+
| | expected `f32`, found `&'static str`
8+
| expected `i32`, found `{float}`
99
|
1010
note: function defined here
1111
--> $DIR/permuted_arguments.rs:5:4
@@ -21,12 +21,12 @@ error[E0308]: arguments to this function are incorrect
2121
--> $DIR/permuted_arguments.rs:12:3
2222
|
2323
LL | many_args(X {}, Y {}, 1, 1.0, "");
24-
| ^^^^^^^^^ ---- ---- - --- -- expected `Y`,found `&'static str`
24+
| ^^^^^^^^^ ---- ---- - --- -- expected `Y`, found `&'static str`
2525
| | | | |
26-
| | | | expected `X`,found `{float}`
27-
| | | expected `&str`,found `{integer}`
28-
| | expected `f32`,found `Y`
29-
| expected `i32`,found `X`
26+
| | | | expected `X`, found `{float}`
27+
| | | expected `&str`, found `{integer}`
28+
| | expected `f32`, found `Y`
29+
| expected `i32`, found `X`
3030
|
3131
note: function defined here
3232
--> $DIR/permuted_arguments.rs:6:4

src/test/ui/argument-suggestions/swapped_arguments.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ error[E0308]: arguments to this function are incorrect
22
--> $DIR/swapped_arguments.rs:8:3
33
|
44
LL | two_args(1.0, 1);
5-
| ^^^^^^^^ --- - expected `f32`,found `{integer}`
5+
| ^^^^^^^^ --- - expected `f32`, found `{integer}`
66
| |
7-
| expected `i32`,found `{float}`
7+
| expected `i32`, found `{float}`
88
|
99
note: function defined here
1010
--> $DIR/swapped_arguments.rs:3:4
@@ -20,9 +20,9 @@ error[E0308]: arguments to this function are incorrect
2020
--> $DIR/swapped_arguments.rs:9:3
2121
|
2222
LL | three_args(1.0, 1, "");
23-
| ^^^^^^^^^^ --- - expected `f32`,found `{integer}`
23+
| ^^^^^^^^^^ --- - expected `f32`, found `{integer}`
2424
| |
25-
| expected `i32`,found `{float}`
25+
| expected `i32`, found `{float}`
2626
|
2727
note: function defined here
2828
--> $DIR/swapped_arguments.rs:4:4
@@ -38,9 +38,9 @@ error[E0308]: arguments to this function are incorrect
3838
--> $DIR/swapped_arguments.rs:10:3
3939
|
4040
LL | three_args( 1, "", 1.0);
41-
| ^^^^^^^^^^ -- --- expected `&str`,found `{float}`
41+
| ^^^^^^^^^^ -- --- expected `&str`, found `{float}`
4242
| |
43-
| expected `f32`,found `&'static str`
43+
| expected `f32`, found `&'static str`
4444
|
4545
note: function defined here
4646
--> $DIR/swapped_arguments.rs:4:4
@@ -56,9 +56,9 @@ error[E0308]: arguments to this function are incorrect
5656
--> $DIR/swapped_arguments.rs:11:3
5757
|
5858
LL | three_args( "", 1.0, 1);
59-
| ^^^^^^^^^^ -- - expected `&str`,found `{integer}`
59+
| ^^^^^^^^^^ -- - expected `&str`, found `{integer}`
6060
| |
61-
| expected `i32`,found `&'static str`
61+
| expected `i32`, found `&'static str`
6262
|
6363
note: function defined here
6464
--> $DIR/swapped_arguments.rs:4:4
@@ -74,11 +74,11 @@ error[E0308]: arguments to this function are incorrect
7474
--> $DIR/swapped_arguments.rs:13:3
7575
|
7676
LL | four_args(1.0, 1, X {}, "");
77-
| ^^^^^^^^^ --- - ---- -- expected `X`,found `&'static str`
77+
| ^^^^^^^^^ --- - ---- -- expected `X`, found `&'static str`
7878
| | | |
79-
| | | expected `&str`,found `X`
80-
| | expected `f32`,found `{integer}`
81-
| expected `i32`,found `{float}`
79+
| | | expected `&str`, found `X`
80+
| | expected `f32`, found `{integer}`
81+
| expected `i32`, found `{float}`
8282
|
8383
note: function defined here
8484
--> $DIR/swapped_arguments.rs:5:4

0 commit comments

Comments
 (0)