
Rust 编译器错误 E0060extern C 可变参数函数必须满足最小实参数量【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust本文围绕 Rust 编译器错误码 E0060对应错误信息被调用的extern C可变参数函数提供的实参数量少于其声明的最少形参展开以rustc_error_codes中的官方错误说明文档为主体结合rustc_hir_typeck中实际产生该错误的类型检查代码讲清楚 E0060 的触发条件、判断逻辑与正确调用方式。读完后你将能够解释 C 风格可变参数c-variadic函数在 Rust FFI 场景下为什么存在最少实参数的概念定位并读懂编译器中判定该错误的具体源码分支在编写extern C声明时避免参数数量不匹配并区分它与 E0061实参过多、E0617变参类型不安全等相邻错误的边界。E0060 是什么C 可变参数函数的最小实参约束官方错误说明文档位于 E0060.md。文档给出的核心事实是外部 C 函数允许声明为可变参数variadic但一个可变参数函数同样有必须传入的最少实参数量——这个最少数量就是函数签名中省略号...之前显式声明的参数个数。文档以 C 的printf为例use std::os::raw::{c_char, c_int}; extern C { fn printf(_: *const c_char, ...) - c_int; } unsafe { printf(); } // error!在这份声明中printf有 1 个显式形参格式字符串指针加一个...可变参数段。因此调用printf()而不传任何实参是非法的编译器会报告 E0060。文档随后给出合法调用的完整示例注意其中针对 Windows MSVC 工具链链接legacy_stdio_definitions静态库的cfg_attr处理这是在实际工程里链接printf时会遇到的细节# use std::os::raw::{c_char, c_int}; # #[cfg_attr(all(windows, target_env msvc), # link(name legacy_stdio_definitions, # kind static, modifiers -bundle))] # extern C { fn printf(_: *const c_char, ...) - c_int; } # fn main() { unsafe { printf(ctest\n.as_ptr()); printf(cnumber %d\n.as_ptr(), 3); printf(c%d, %d\n.as_ptr(), 10, 5); } # }三种调用形态说明了规则的两个方面可变参数段可以完全省略只传最少实参第一个示例可变参数段可以传入任意数量的额外实参后两个示例分别传了 1 个、2 个额外实参。换句话说对于最少 N 个形参 ...的 C 可变参数函数合法调用区间是N、N1、N2、...个实参E0060 正是实参数 N时的报错。源码印证E0060 在类型检查阶段如何产生从源码结构看E0060 的判定发生在 HIR 类型检查rustc_hir_typeck的实参检查流程中具体在 checks.rs 的check_expr实参核对逻辑里。关键代码有三处正好构成完整的判定链1. 确定最少实参数与实际实参数。在 checks.rs#L356-L357let minimum_input_count expected_input_tys.len(); let provided_arg_count provided_args.len();minimum_input_count取的是函数签名中显式声明的形参列表长度不含...与文档中最少实参数 省略号之前的参数个数的描述完全一致。2. 预判调用看起来是否满足。在 checks.rs#L425-L429编译器对 c-variadic 函数与非 variadic 函数采用不同的满足条件let mut call_appears_satisfied if c_variadic { provided_arg_count minimum_input_count } else { provided_arg_count minimum_input_count };即普通 Rust 函数要求实参数恰好等于形参数而 C 可变参数函数只要求实参数不小于最少形参数。源码注释也点明了原因如果 c_variadic提供的实参必须 函数要求的最小数量否则必须完全相等因为 Rust 目前不支持变长参数函数。3. 指定 E0060 错误码并上报。在 checks.rs#L487-L489if c_variadic provided_arg_count minimum_input_count { err_code E0060; }当是 C 可变参数函数且实参数少于最少形参数同时成立时错误码从默认值切换为 E0060普通函数实参数不符时默认为 E0061见 checks.rs#L318 处的let mut err_code E0061;最终经由report_arg_errors统一报告见 checks.rs#L558-L589。变参实参的类型检查边界与 E0617 的分工E0060 只解决数量下限问题而...之后的每个实参没有声明类型类型检查器对它们采取宽松处理但仍有安全约束。在 checks.rs#L454-L461 可以看到对于索引达到minimum_input_count之后的实参即落入可变参数段的实参常规的类型兼容性检查被跳过continue因为编译器并不知道 C 端期望的类型。但 C 语言对变参有隐式提升规则如f32提升为f64、窄整型提升为c_intRust 拒绝自动提升改为要求显式转换。在 checks.rs#L491-L556 中编译器会检查每个变参实参是否实现VaArgSafe特性通过 lang item 查找见 checks.rs#L524-L530不满足的类型会触发E0617并给出显式转换建议f32→ 建议转为c_doublei8/i16/bool→ 建议转为c_intu8/u16→ 建议转为c_uint函数项FnDef→ 建议取函数指针PassFnItemToVariadicFunction诊断。源码注释还指出一个目标相关的事实VaArgSafe是实现变参安全的唯一权威来源source of truth在某些嵌入式目标上c_double是f32、c_int是i16这些类型在那些目标上实现VaArgSafe而在其他目标上不实现。这就形成了清晰的错误分工E0060 管最少数量的下限E0061 管非变参函数的精确数量E0617 管变参段的类型安全。实战要点与排查建议结合文档示例与源码判定逻辑编写或排查涉及extern C可变参数函数的代码时可以按以下清单操作数省略号前的形参个数。extern C { fn f(a: T, b: U, ...) - R; }的最少实参数是 2调用时少于 2 个实参即触发 E0060。注意 Rust 自身的函数不能声明...该能力只属于extern C声明见 checks.rs#L423-L424 源码注释Rust 目前不支持变长参数函数。所有显式形参位置必须类型匹配。E0060 只报数量不足若数量足够但前 N 个实参类型错误报的是类型不兼容错误而非 E0060。变参段实参会经过VaArgSafe检查。如果你传入f32、窄整型等预期会收到 E0617 并附显式转换建议如as c_double这是设计行为而非误报。调用发生在unsafe块中。C 变参函数没有类型信息保护变参段Rust 将其置于extern块语义之下调用本身要求unsafe上下文文档示例中的unsafe { ... }包裹即体现这一点。Windows MSVC 平台链接注意。文档示例中用#[cfg_attr(all(windows, target_env msvc), link(...))]追加legacy_stdio_definitions静态库这是在该平台链接 C 标准库可变参数函数如printf时常见的补充链接步骤。小结E0060 是 Rust FFI 对 C 可变参数函数最少实参数约束的落地extern C声明中...之前的每个形参都必须有对应实参printf()这类空调用因不满足下限而被拒绝。错误码的赋值点在 rustc_hir_typeck 的 checks.rs 中判定条件简洁明确c_variadic provided_arg_count minimum_input_count与之配合的VaArgSafe检查E0617则把 C 变参的隐式提升风险显式化为编译期错误。理解这条判定链后遇到参数数量类错误时可先按 E0060/E0061/E0617 的分工定位问题属于数量下限精确数量还是变参类型再对照 E0060 官方说明 修正调用方式。【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考