Rollup merge of #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 #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 #92364, and `@estebank` as reviewer of that PR.
fixes #97484
r? `@jackh726` this should be _much_ easier to review than the other PR 😅
This commit is contained in:
Michael Goulet 2022-06-08 13:32:18 -07:00 committed by GitHub
commit 1922f0b980
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 95 additions and 47 deletions

View File

@ -445,16 +445,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let found_errors = !errors.is_empty();
errors.drain_filter(|error| {
let Error::Invalid(input_idx, arg_idx, Compatibility::Incompatible(error)) = error else { return false };
let Error::Invalid(input_idx, arg_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
let expected_ty = expected_input_tys[*arg_idx];
let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap();
let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap_or_else(|| tcx.ty_error());
let cause = &self.misc(provided_args[*input_idx].span);
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
if let Some(e) = error {
if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
self.report_and_explain_type_error(trace, e).emit();
return true;
}
if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
self.report_and_explain_type_error(trace, e).emit();
return true;
}
false
});
@ -585,7 +583,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)) = errors.iter().next()
{
let expected_ty = expected_input_tys[*arg_idx];
let provided_ty = final_arg_types[*arg_idx].map(|ty| ty.0).unwrap();
let provided_ty = final_arg_types[*input_idx]
.map(|ty| ty.0)
.unwrap_or_else(|| tcx.ty_error());
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);
@ -595,7 +595,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&mut err,
&provided_args[*input_idx],
provided_ty,
final_arg_types[*input_idx].map(|ty| ty.1).unwrap(),
final_arg_types[*input_idx]
.map(|ty| ty.1)
.unwrap_or_else(|| tcx.ty_error()),
None,
None,
);
@ -652,7 +654,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match error {
Error::Invalid(input_idx, arg_idx, compatibility) => {
let expected_ty = expected_input_tys[arg_idx];
let provided_ty = final_arg_types[input_idx].map(|ty| ty.0).unwrap();
let provided_ty = final_arg_types[input_idx]
.map(|ty| ty.0)
.unwrap_or_else(|| 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 {
@ -674,8 +678,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.emit_coerce_suggestions(
&mut err,
&provided_args[input_idx],
final_arg_types[input_idx].map(|ty| ty.0).unwrap(),
final_arg_types[input_idx].map(|ty| ty.1).unwrap(),
provided_ty,
// FIXME(compiler-errors): expected_ty?
final_arg_types[input_idx]
.map(|ty| ty.1)
.unwrap_or_else(|| tcx.ty_error()),
None,
None,
);
@ -860,7 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let first_expected_ty =
self.resolve_vars_if_possible(expected_input_tys[arg_idx]);
let first_provided_ty = if let Some((ty, _)) = final_arg_types[input_idx] {
format!(",found `{}`", ty)
format!(", found `{}`", ty)
} else {
String::new()
};
@ -872,7 +879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.resolve_vars_if_possible(expected_input_tys[other_arg_idx]);
let other_provided_ty =
if let Some((ty, _)) = final_arg_types[other_input_idx] {
format!(",found `{}`", ty)
format!(", found `{}`", ty)
} else {
String::new()
};
@ -888,14 +895,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Error::Permutation(args) => {
for (dst_arg, dest_input) in args {
let expected_ty =
self.resolve_vars_if_possible(expected_input_tys[dest_input]);
let provided_ty = if let Some((ty, _)) = final_arg_types[dst_arg] {
format!(",found `{}`", ty)
self.resolve_vars_if_possible(expected_input_tys[dst_arg]);
let provided_ty = if let Some((ty, _)) = final_arg_types[dest_input] {
format!(", found `{}`", ty)
} else {
String::new()
};
labels.push((
provided_args[dst_arg].span,
provided_args[dest_input].span,
format!("expected `{}`{}", expected_ty, provided_ty),
));
}

View File

@ -48,9 +48,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/basic.rs:23:5
|
LL | swapped("", 1);
| ^^^^^^^ -- - expected `&str`,found `{integer}`
| ^^^^^^^ -- - expected `&str`, found `{integer}`
| |
| expected `u32`,found `&'static str`
| expected `u32`, found `&'static str`
|
note: function defined here
--> $DIR/basic.rs:16:4
@ -66,10 +66,10 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/basic.rs:24:5
|
LL | permuted(Y {}, Z {}, X {});
| ^^^^^^^^ ---- ---- ---- expected `Z`,found `X`
| ^^^^^^^^ ---- ---- ---- expected `Z`, found `X`
| | |
| | expected `Y`,found `Z`
| expected `X`,found `Y`
| | expected `Y`, found `Z`
| expected `X`, found `Y`
|
note: function defined here
--> $DIR/basic.rs:17:4

View File

@ -0,0 +1,14 @@
struct A;
struct B;
struct C;
struct D;
struct E;
struct F;
struct G;
fn foo(a: &A, d: D, e: &E, g: G) {}
fn main() {
foo(&&A, B, C, D, E, F, G);
//~^ ERROR this function takes 4 arguments but 7 arguments were supplied
}

View File

@ -0,0 +1,27 @@
error[E0061]: this function takes 4 arguments but 7 arguments were supplied
--> $DIR/issue-97484.rs:12:5
|
LL | foo(&&A, B, C, D, E, F, G);
| ^^^ - - - argument unexpected
| | |
| | argument of type `&E` unexpected
| argument of type `D` unexpected
|
note: function defined here
--> $DIR/issue-97484.rs:9:4
|
LL | fn foo(a: &A, d: D, e: &E, g: G) {}
| ^^^ ----- ---- ----- ----
help: consider removing the ``
|
LL - foo(&&A, B, C, D, E, F, G);
LL + foo(&&A, B, C, D, E, F, G);
|
help: remove the extra arguments
|
LL | foo(&&A, D, {&E}, G);
| ~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
For more information about this error, try `rustc --explain E0061`.

View File

@ -76,10 +76,10 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/mixed_cases.rs:20:3
|
LL | three_args("", X {}, 1);
| ^^^^^^^^^^ -- ---- - expected `&str`,found `{integer}`
| ^^^^^^^^^^ -- ---- - expected `&str`, found `{integer}`
| | |
| | expected `f32`, found struct `X`
| expected `i32`,found `&'static str`
| expected `i32`, found `&'static str`
|
note: function defined here
--> $DIR/mixed_cases.rs:6:4
@ -98,8 +98,8 @@ LL | three_args("", 1);
| ^^^^^^^^^^ -- -
| | |
| | an argument of type `f32` is missing
| | expected `&str`,found `{integer}`
| expected `i32`,found `&'static str`
| | expected `&str`, found `{integer}`
| expected `i32`, found `&'static str`
|
note: function defined here
--> $DIR/mixed_cases.rs:6:4

View File

@ -2,10 +2,10 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/permuted_arguments.rs:10:3
|
LL | three_args(1.0, "", 1);
| ^^^^^^^^^^ --- -- - expected `&str`,found `{integer}`
| ^^^^^^^^^^ --- -- - expected `&str`, found `{integer}`
| | |
| | expected `f32`,found `&'static str`
| expected `i32`,found `{float}`
| | expected `f32`, found `&'static str`
| expected `i32`, found `{float}`
|
note: function defined here
--> $DIR/permuted_arguments.rs:5:4
@ -21,12 +21,12 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/permuted_arguments.rs:12:3
|
LL | many_args(X {}, Y {}, 1, 1.0, "");
| ^^^^^^^^^ ---- ---- - --- -- expected `Y`,found `&'static str`
| ^^^^^^^^^ ---- ---- - --- -- expected `Y`, found `&'static str`
| | | | |
| | | | expected `X`,found `{float}`
| | | expected `&str`,found `{integer}`
| | expected `f32`,found `Y`
| expected `i32`,found `X`
| | | | expected `X`, found `{float}`
| | | expected `&str`, found `{integer}`
| | expected `f32`, found `Y`
| expected `i32`, found `X`
|
note: function defined here
--> $DIR/permuted_arguments.rs:6:4

View File

@ -2,9 +2,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:8:3
|
LL | two_args(1.0, 1);
| ^^^^^^^^ --- - expected `f32`,found `{integer}`
| ^^^^^^^^ --- - expected `f32`, found `{integer}`
| |
| expected `i32`,found `{float}`
| expected `i32`, found `{float}`
|
note: function defined here
--> $DIR/swapped_arguments.rs:3:4
@ -20,9 +20,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:9:3
|
LL | three_args(1.0, 1, "");
| ^^^^^^^^^^ --- - expected `f32`,found `{integer}`
| ^^^^^^^^^^ --- - expected `f32`, found `{integer}`
| |
| expected `i32`,found `{float}`
| expected `i32`, found `{float}`
|
note: function defined here
--> $DIR/swapped_arguments.rs:4:4
@ -38,9 +38,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:10:3
|
LL | three_args( 1, "", 1.0);
| ^^^^^^^^^^ -- --- expected `&str`,found `{float}`
| ^^^^^^^^^^ -- --- expected `&str`, found `{float}`
| |
| expected `f32`,found `&'static str`
| expected `f32`, found `&'static str`
|
note: function defined here
--> $DIR/swapped_arguments.rs:4:4
@ -56,9 +56,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:11:3
|
LL | three_args( "", 1.0, 1);
| ^^^^^^^^^^ -- - expected `&str`,found `{integer}`
| ^^^^^^^^^^ -- - expected `&str`, found `{integer}`
| |
| expected `i32`,found `&'static str`
| expected `i32`, found `&'static str`
|
note: function defined here
--> $DIR/swapped_arguments.rs:4:4
@ -74,11 +74,11 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:13:3
|
LL | four_args(1.0, 1, X {}, "");
| ^^^^^^^^^ --- - ---- -- expected `X`,found `&'static str`
| ^^^^^^^^^ --- - ---- -- expected `X`, found `&'static str`
| | | |
| | | expected `&str`,found `X`
| | expected `f32`,found `{integer}`
| expected `i32`,found `{float}`
| | | expected `&str`, found `X`
| | expected `f32`, found `{integer}`
| expected `i32`, found `{float}`
|
note: function defined here
--> $DIR/swapped_arguments.rs:5:4