Skip to content

Commit

Permalink
Rollup merge of #130437 - jder:issue-130372, r=compiler-errors
Browse files Browse the repository at this point in the history
Avoid crashing on variadic functions when producing arg-mismatch errors

Fixes #130372 by accommodating how variadic functions change the argument list length between HIR body and FnDecls.

Also degrades the zip_eq to a debug_assert! to match other asserts in the area to avoid being disruptive to users. There is at least one other crash in this area I am working on in #130400 and also considering how we might refactor some of this code to hoist some of this logic up higher.

r? `@compiler-errors`
  • Loading branch information
matthiaskrgr authored Sep 16, 2024
2 parents 852e08e + 45eceb2 commit 14ee69c
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 31 deletions.
17 changes: 13 additions & 4 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2619,9 +2619,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
is_method: bool,
) -> Option<Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
let fn_node = self.tcx.hir().get_if_local(def_id)?;
let fn_decl = fn_node.fn_decl()?;

let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_node
.fn_decl()?
let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_decl
.inputs
.into_iter()
.skip(if is_method { 1 } else { 0 })
Expand All @@ -2642,7 +2642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
})
.collect();

let params: Vec<&hir::Param<'_>> = self
let mut params: Vec<&hir::Param<'_>> = self
.tcx
.hir()
.body(fn_node.body_id()?)
Expand All @@ -2651,7 +2651,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.skip(if is_method { 1 } else { 0 })
.collect();

Some(generic_params.into_iter().zip_eq(params).collect())
// The surrounding code expects variadic functions to not have a parameter representing
// the "..." parameter. This is already true of the FnDecl but not of the body params, so
// we drop it if it exists.

if fn_decl.c_variadic {
params.pop();
}

debug_assert_eq!(params.len(), generic_params.len());
Some(generic_params.into_iter().zip(params).collect())
}
}

Expand Down
9 changes: 0 additions & 9 deletions tests/crashes/130372-1.rs

This file was deleted.

11 changes: 0 additions & 11 deletions tests/crashes/130372-2.rs

This file was deleted.

7 changes: 0 additions & 7 deletions tests/crashes/130372-3.rs

This file was deleted.

12 changes: 12 additions & 0 deletions tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![feature(c_variadic)]

// Regression test that covers all 3 cases of https://github.com/rust-lang/rust/issues/130372

unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {}

pub fn main() {
unsafe {
test_va_copy();
//~^ ERROR this function takes at least 1 argument but 0 arguments were supplied
}
}
19 changes: 19 additions & 0 deletions tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
--> $DIR/mismatch-args-vargs-issue-130372.rs:9:9
|
LL | test_va_copy();
| ^^^^^^^^^^^^-- argument #1 of type `u64` is missing
|
note: function defined here
--> $DIR/mismatch-args-vargs-issue-130372.rs:5:22
|
LL | unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {}
| ^^^^^^^^^^^^ ------
help: provide the argument
|
LL | test_va_copy(/* u64 */);
| ~~~~~~~~~~~

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0060`.

0 comments on commit 14ee69c

Please sign in to comment.