Unnamed repository; edit this file 'description' to name the repository.
Don't count C-variadic `...` as a parameter for fn pointers
When lowering a C-variadic function-pointer type such as `unsafe extern "C" fn(u8, ...) -> i32`, the `...` slot was being included in the lowered parameter list as a real input. The arity check then required the variadic slot to be supplied, producing a spurious E0107 ("wrong number of arguments") at the call site even though rustc accepts the code. The function-declaration lowering path already filters the variadic param out; this applies the same filtering to the fn-pointer path. Fixes rust-lang/rust-analyzer#22573
Lynn Gabbay 5 weeks ago
parent 5c7ce22 · commit e9d9dc1
-rw-r--r--crates/hir-def/src/expr_store/lower.rs1
-rw-r--r--crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs24
2 files changed, 25 insertions, 0 deletions
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index 3094e08a53..bbc3f5333a 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -671,6 +671,7 @@ impl<'db> ExprCollector<'db> {
}
pl.params()
+ .filter(|it| it.dotdotdot_token().is_none())
.map(|it| {
let type_ref = self.lower_type_ref_opt(it.ty(), impl_trait_lower_fn);
let name = match it.pat() {
diff --git a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs
index f6293e35d0..d1c3d1c5df 100644
--- a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs
+++ b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs
@@ -355,6 +355,30 @@ fn f() {
}
#[test]
+ fn varargs_fn_pointer() {
+ check_diagnostics(
+ r#"
+struct Funcs {
+ f: unsafe extern "C" fn(u8, u8, ...) -> i32,
+ g: unsafe extern "C" fn(...) -> i32,
+}
+
+fn f(funcs: Funcs) {
+ unsafe {
+ (funcs.f)(0, 1);
+ (funcs.f)(0, 1, 2);
+ (funcs.f)(0);
+ //^ error: expected 2 arguments, found 1
+ (funcs.g)();
+ (funcs.g)(0);
+ (funcs.g)(0, 1);
+ }
+}
+ "#,
+ )
+ }
+
+ #[test]
fn arg_count_lambda() {
check_diagnostics(
r#"