ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Rust 编译器错误 E0094:`[rustc_intrinsic]` 内建函数泛型参数数量不正确的原理与修复

Rust 编译器错误 E0094:`[rustc_intrinsic]` 内建函数泛型参数数量不正确的原理与修复 Rust 编译器错误 E0094#[rustc_intrinsic]内建函数泛型参数数量不正确的原理与修复【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rustE0094An invalid number of generic parameters was passed to an intrinsic function是 rustc 在类型检查阶段针对#[rustc_intrinsic]声明发出的错误当你在代码中声明的内建函数intrinsic携带的泛型参数数量与编译器内部登记表的期望值不一致时编译器会报告 E0094。读完本文你将理解该错误的确切触发条件、编译器中完成参数数量比对的具体源码逻辑并掌握如何依据内建函数签名表快速定位和修复参数数量错误。什么是 E0094错误触发条件与复现官方错误示例Rust 错误码文档 E0094 给出的最小复现场景是一个size_of内建函数被声明成了带两个类型参数的形式而编译器期望它只接受一个类型参数#![feature(intrinsics)] #![allow(internal_features)] #[rustc_intrinsic] fn size_ofT, U() - usize; // error: intrinsic has wrong number // of type parameters这里的要点在于size_of的签名声明中T, U两个泛型参数都是你自己写的而编译器对size_of这个内建名称有一份内置的期望签名。两者数量对不上就会在分析阶段直接报错。文档同时给出了正确写法作为对照#![feature(intrinsics)] #![allow(internal_features)] #[rustc_intrinsic] fn size_ofT() - usize; // ok!即请核对你提供的泛型参数数量并与 Rust 源码中该内建函数的声明保持一致。实际的诊断消息从当前仓库的诊断定义看E0094 对应的诊断结构体是WrongNumberOfGenericArgumentsToIntrinsic定义于 rustc_hir_analysis 诊断模块#[derive(Diagnostic)] #[diag(intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}, code E0094)] pub(crate) struct WrongNumberOfGenericArgumentsToIntrinsica { #[primary_span] #[label( expected {$expected} {$descr} {$expected - [one] parameter *[other] parameters } )] pub span: Span, pub found: usize, pub expected: usize, pub descr: a str, }由此可以读出实际报错消息的完整形态主错误信息为intrinsic has wrong number of {type|lifetime|const} parameters: found {N}, expected {M}例如intrinsic has wrong number of type parameters: found 2, expected 1附加 label 会给出期望值并处理单复数expected 1 type parameter/expected 2 type parametersdescr字段取值为lifetime、type、const三者之一——也就是说E0094 并不只针对类型参数生命周期参数与 const 参数数量不匹配同样会触发本错误。编译器如何触发 E0094源码级检查流程检查入口check_intrinsic_type内建函数的签名合法性检查统一收敛在 check/intrinsic.rs 的check_intrinsic_type函数中。该函数首先从TyCtxt取出该内建项的泛型信息然后根据内建函数名称在一个巨大的match表达式中查表得到四元组(n_tps, n_cts, inputs, output)——分别代表期望的类型参数个数、const 参数个数、输入参数类型列表和输出类型。以与本文错误示例直接相关的size_of为例表中登记如下intrinsic.rs 第 290 行sym::size_of | sym::align_of | sym::variant_count (1, 0, vec![], tcx.types.usize),即1 个类型参数、0 个 const 参数、无输入参数、返回usize。其他内建函数的登记可以体现参数数量的多样性内建函数类型参数数const 参数数说明size_of/align_of/variant_count10返回usizetransmute/transmute_unchecked20param(0)转为param(1)atomic_load/atomic_store12第 2 个 const 参数是内存序atomic_cxchg/atomic_cxchgweak12返回(param(0), bool)元组aggregate_raw_ptr30返回param(0)autodiff40返回param(3)如果内建函数名称在表中根本不存在会走到other分支并改用相邻错误码E0093UnrecognizedIntrinsicFunction报告unrecognized intrinsic function同时提示如果你正在添加一个新的 intrinsic请记得更新check_intrinsic_type见 diagnostics.rs 第 197-205 行。因此排障时需要注意区分名字不认识是 E0093名字认识但参数数量对不上才是 E0094。数量比对equate_intrinsic_type拿到期望数量后真正的比对发生在 equate_intrinsic_type 中fn equate_intrinsic_typetcx( tcx: TyCtxttcx, span: Span, def_id: LocalDefId, n_tps: usize, n_lts: usize, n_cts: usize, sig: ty::PolyFnSigtcx, ) { let (generics, span) match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) { (tcx.generics_of(def_id), generics.span) } _ tcx.dcx().span_bug(span, intrinsic must be a function), }; let own_counts generics.own_counts(); let gen_count_ok |found: usize, expected: usize, descr: str| - bool { if found ! expected { tcx.dcx().emit_err(WrongNumberOfGenericArgumentsToIntrinsic { span, found, expected, descr, }); false } else { true } }; if gen_count_ok(own_counts.lifetimes, n_lts, lifetime) gen_count_ok(own_counts.types, n_tps, type) gen_count_ok(own_counts.consts, n_cts, const) { /* 全部通过后才继续检查函数签名 */ } }从源码结构看这里有两个值得注意的细节逐项独立报告gen_count_ok闭包对 lifetime、type、const 三类参数分别调用且用短路串联。一旦某一类数量不匹配立即emit_err并返回false后续的check_function_signature对输入/输出类型的逐参数检查就不会执行——也就是说参数数量错误是先决条件签名体检查只在数量全部正确的前提下才进行。descr决定错误措辞闭包第三个参数即诊断中的descr所以你在错误信息中看到的wrong number of type parameters/wrong number of lifetime parameters/wrong number of const parameters分别对应三次调用的字面量。顺带一提safety 一致性检查同一文件中还有一份按名称排序的安全内建函数清单intrinsic_operation_unsafetyintrinsic.rs 第 61-236 行覆盖abort、breakpoint、size_of、type_name等编译器认为是 safe 的内建。若 core 库中该内建的unsafe标记与清单不符会单独报错intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics。它虽然不属于 E0094但与参数数量检查同属内建函数声明合法性这一层排障时可以一并留意。如何修复以签名表为唯一事实来源标准修复步骤结合 E0094 文档给出的建议与源码中的检查流程修复路径是明确的读错误消息中的数字found N, expected M直接告诉你实际写了多少、应该写多少descr告诉你错的是类型、生命周期还是 const 参数定位期望签名的权威来源到 check_intrinsic_type 的 match 表 中按内建函数名找到对应条目(n_tps, n_cts, inputs, output)就是编译器认可的完整签名修改你的#[rustc_intrinsic]声明使泛型参数数量及参数类型与表中登记一致例如把fn size_ofT, U() - usize;改为fn size_ofT() - usize;注意参数序号的语义表中param(0)、param(1)引用的是按声明顺序的泛型参数。删减参数时还要检查输入/输出类型中是否引用了被你删除的序号如transmute依赖param(0)与param(1)避免修好数量后又引发后续签名检查报错。添加新内建函数时的三处同步源码注释明确要求新增内建函数时必须同步三处intrinsic.rs 第 238-239 行/// Remember to add all intrinsics here, in compiler/rustc_codegen_llvm/src/intrinsic.rs, /// and in library/core/src/intrinsics.rs.即rustc_hir_analysis的检查表、rustc_codegen_llvm的代码生成实现、以及 core 库中的声明三处必须保持一致。只改了其中一处编译期就会以 E0093/E0094 或 safety mismatch 等形式暴露出来。背景知识core 库中的内建函数声明长什么样core标准库的 intrinsics 模块 集中声明了这些内建函数其模块文档说明了几个对使用本错误码很有用处的背景事实该模块标记为#![unstable(feature core_intrinsics, ...)]理由明确写着内建函数不太可能稳定应通过标准库其余部分提供的稳定接口来使用——因此在日常业务代码中你几乎不会手写#[rustc_intrinsic]E0094 主要出现在开发或修改编译器/标准库本身的场景文档指出内建函数的实现位置分布一部分在 MIR 层面被 lowerrustc_mir_transform中的lower_intrinsics其余由 codegen-SSA/LLVM 后端以及 const-eval 解释器实现。这也解释了为什么检查表中每个条目都登记了完整的输入输出类型——它们是所有后端共享的契约core 库中还存在mir、simd、gpu等子模块继续扩展内建声明对应检查表中的simd_*、sve_*、gpu_launch_sized_workgroup_mem等条目参数数量更多、结构更复杂排障时同样以检查表条目为准。排障速查清单报错intrinsic has wrong number of type parameters: found 2, expected 1你多写了一个类型参数按检查表条目删除多余参数典型如文档示例中的size_ofT, U→size_ofT报错措辞是lifetime parameters或const parameters错误不在类型参数而在生命周期或 const 参数数量注意原子类内建通常带有 1~2 个 const 参数如atomic_load为 1 类型 2 const报unrecognized intrinsic functionE0093而非 E0094内建名称本身就不在编译器登记表中先核对拼写或确认该名称是否尚未在当前工具链版本中实现同时出现 safety mismatch说明该内建在 core 库的声明unsafe与否与编译器清单不一致参考 intrinsic_operation_unsafety 中的清单核对适用前提本错误仅在开启内建函数相关的内部特性文档示例使用#![feature(intrinsics)]#![allow(internal_features)]时才会触发检查逻辑随编译器版本演进具体条目以当前仓库中 check/intrinsic.rs 的实际内容为准。【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表