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:
commit
1922f0b980
7 changed files with 95 additions and 47 deletions
|
@ -445,17 +445,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let found_errors = !errors.is_empty();
|
let found_errors = !errors.is_empty();
|
||||||
|
|
||||||
errors.drain_filter(|error| {
|
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 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 cause = &self.misc(provided_args[*input_idx].span);
|
||||||
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
|
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(_)) {
|
if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
|
||||||
self.report_and_explain_type_error(trace, e).emit();
|
self.report_and_explain_type_error(trace, e).emit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
false
|
false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -585,7 +583,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
)) = errors.iter().next()
|
)) = errors.iter().next()
|
||||||
{
|
{
|
||||||
let expected_ty = expected_input_tys[*arg_idx];
|
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 expected_ty = self.resolve_vars_if_possible(expected_ty);
|
||||||
let provided_ty = self.resolve_vars_if_possible(provided_ty);
|
let provided_ty = self.resolve_vars_if_possible(provided_ty);
|
||||||
let cause = &self.misc(provided_args[*input_idx].span);
|
let cause = &self.misc(provided_args[*input_idx].span);
|
||||||
|
@ -595,7 +595,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&mut err,
|
&mut err,
|
||||||
&provided_args[*input_idx],
|
&provided_args[*input_idx],
|
||||||
provided_ty,
|
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,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -652,7 +654,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
match error {
|
match error {
|
||||||
Error::Invalid(input_idx, arg_idx, compatibility) => {
|
Error::Invalid(input_idx, arg_idx, compatibility) => {
|
||||||
let expected_ty = expected_input_tys[arg_idx];
|
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 expected_ty = self.resolve_vars_if_possible(expected_ty);
|
||||||
let provided_ty = self.resolve_vars_if_possible(provided_ty);
|
let provided_ty = self.resolve_vars_if_possible(provided_ty);
|
||||||
if let Compatibility::Incompatible(error) = &compatibility {
|
if let Compatibility::Incompatible(error) = &compatibility {
|
||||||
|
@ -674,8 +678,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.emit_coerce_suggestions(
|
self.emit_coerce_suggestions(
|
||||||
&mut err,
|
&mut err,
|
||||||
&provided_args[input_idx],
|
&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(),
|
// FIXME(compiler-errors): expected_ty?
|
||||||
|
final_arg_types[input_idx]
|
||||||
|
.map(|ty| ty.1)
|
||||||
|
.unwrap_or_else(|| tcx.ty_error()),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -888,14 +895,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
Error::Permutation(args) => {
|
Error::Permutation(args) => {
|
||||||
for (dst_arg, dest_input) in args {
|
for (dst_arg, dest_input) in args {
|
||||||
let expected_ty =
|
let expected_ty =
|
||||||
self.resolve_vars_if_possible(expected_input_tys[dest_input]);
|
self.resolve_vars_if_possible(expected_input_tys[dst_arg]);
|
||||||
let provided_ty = if let Some((ty, _)) = final_arg_types[dst_arg] {
|
let provided_ty = if let Some((ty, _)) = final_arg_types[dest_input] {
|
||||||
format!(", found `{}`", ty)
|
format!(", found `{}`", ty)
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
labels.push((
|
labels.push((
|
||||||
provided_args[dst_arg].span,
|
provided_args[dest_input].span,
|
||||||
format!("expected `{}`{}", expected_ty, provided_ty),
|
format!("expected `{}`{}", expected_ty, provided_ty),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
14
src/test/ui/argument-suggestions/issue-97484.rs
Normal file
14
src/test/ui/argument-suggestions/issue-97484.rs
Normal 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
|
||||||
|
}
|
27
src/test/ui/argument-suggestions/issue-97484.stderr
Normal file
27
src/test/ui/argument-suggestions/issue-97484.stderr
Normal 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`.
|
Loading…
Add table
Add a link
Reference in a new issue