Rust 编译器错误 E0805 详解属性参数数量错误从#[inline]示例到 rustc_attr_parsing 实现【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust本文围绕 rustc 错误代码 E0805“An attribute was given an invalid number of arguments”展开先继承官方错误文档中给出的错误示例与修复方式再结合 rust 仓库源码属性解析诊断实现、inline 属性定义与 UI 测试E0805 测试用例说明该错误在什么条件下触发、诊断信息的完整形态以及各主流属性inline、cfg、repr等的合法参数形式帮助你快速定位并修复属性参数数量不匹配的问题。E0805 的定义属性被给了错误数量的参数E0805 的官方文档定义只有一句话属性被赋予了无效数量的参数An attribute was given an invalid number of arguments。这里的“参数”指的是属性括号(...)内部的 meta-item而不是函数调用的实参。官方文档 E0805.md 给出的错误示例如下#[inline()] // error! should either have a single argument, or no parentheses fn foo() {} #[inline(always, never)] // error! should have only one argument, not two fn bar() {}这里恰好覆盖了 E0805 的两类触发形态也是该错误全部成因的缩影空括号0 个参数但属性要求恰好 1 个#[inline()]。inline的合法形式是“不带括号”或“括号里恰好一个关键字”空括号既不是前者也不是后者因此报“expected an argument here”。参数过多2 个及以上参数但属性要求恰好 1 个#[inline(always, never)]。inline只接受一个参数always和never同时出现时触发“expected a single argument here”。修复方式按属性的模板补齐或删减参数官方文档给出的修复原则是给属性提供它所需要的正确数量参数。对inline而言就是两种合法写法之一——完全不给参数#[inline] fn foo() {}或者只给一个参数#[inline(always)] fn foo() {}补充说明#[inline]的完整参数空间从源码 attributes/inline.rs 中的属性模板可以看到它声明为const TEMPLATE: AttributeTemplate template!( Word, List: [always, never], https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute );即模板为Word | List列表内容限定为always或never见 inline.rs L30-L34。其convert函数对三种入参形态的处理是inline.rs L37-L54ArgParser::NoArgs裸#[inline]编译为InlineAttr::Hint相当于“可内联提示”ArgParser::List(list)先调用cx.expect_single(list)强制列表里恰好有一个元素这一步失败即产生 E0805再检查该元素是always还是never检查失败则转为 E0539 的“期望特定关键字”诊断其他形态如 namevalue 的#[inline(x 1)]由模板直接拒绝。所以排查 E0805 时第一步永远是查该属性模板允许的参数个数0 个、恰好 1 个、至少 N 个、任意个列表。E0805 的诊断输出长什么样仅看“expected an argument here”这一句容易遗漏上下文。仓库中的 UI 测试 tests/ui/span/E0805.rs 提供了一个真实触发场景——cfg!宏缺少参数pub fn main() { if cfg!(not()) { } //~ ERROR E0805 }其对应的预期诊断输出 tests/ui/span/E0805.stderr 完整展示了 E0805 诊断的结构error[E0805]: malformed cfg macro input -- $DIR/E0805.rs:2:8 | LL | if cfg!(not()) { } | ^^^^^^^^--^ | | | expected an argument here | note: for more information, visit https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute help: must be of the form | LL - if cfg!(not()) { } LL if cfg!(predicate) { }几个值得注意的点诊断的标题是malformed ... input而不是 E0805 的描述本身且标题前缀为error[E0805]。因为 E0805 是在 E0539 的基础诊断之上“升级”出来的下一节详述标题沿用了 E0539 的“malformed{name}{description} input”句式。诊断末尾会附带该属性官方参考文档的链接note:一行以及**“must be of the form”形式的修复建议**如cfg!(predicate)这些信息来自属性模板声明的文档 URL 与参数模板遇到诊断时可以直接照着建议改写。cfg!是宏而非属性但cfg!的参数解析复用同一套机制所以它同样报 E0805——这说明 E0805 覆盖范围是所有基于属性解析器校验参数数量的内置属性与相关宏并非只有#[...]属性。仓库中另有多个.stderr文件包含 E0805如 tests/ui/repr/malformed-repr-hints.stderr 等印证了repr等属性的参数数量错误也归入此码。源码级机制E0805 在哪里被“点亮”在 compiler/rustc_attr_parsing/src/diagnostics.rs 中AttributeParseError实现Diagnostictrait 时基础错误码是E0539“malformed{name}{description} input”见 L1600-L1602然后按失败原因改写错误码。其中与 E0805 直接相关的两个分支是diagnostics.rs L1637-L1644AttributeParseErrorReason::ExpectedSingleArgument { diag.span_label(self.span, expected a single argument here); diag.code(E0805); } AttributeParseErrorReason::ExpectedArgument { diag.span_label(self.span, expected an argument here); diag.code(E0805); }也就是说ExpectedSingleArgument给了多于 1 个参数→ 标签“expected a single argument here”错误码改写为 E0805ExpectedArgument要求恰好 1 个参数但实际为 0 个→ 标签“expected an argument here”错误码同样改写为 E0805。而同一个match里的其他分支说明了 E0805 与邻居错误码的边界这对排查很有帮助失败原因诊断标签错误码ExpectedSingleArgumentexpected a single argument hereE0805ExpectedArgumentexpected an argument hereE0805ExpectedAtLeastOneArgumentexpected at least 1 argument hereE0539基础码ExpectedNoArgsdidnt expect any arguments hereE0565ExpectedList/ExpectedListOrNoArgs/ExpectedNameValueOrNoArgsexpected this to be a list 等E0539基础码DuplicateKeyfoundkeyused as a key more than onceE0538从这张对照可以推断“参数个数不符”只在“恰好 1 个”这个精确约束下才升级为 E0805“至少 1 个但给了 0 个”“该带参数却没带括号”等形态留在 E0539 名下而“该无参数却给了参数”则是 E0565。E0539 的完整文档可参考 E0539.md。expect_single参数个数约束的落点E0805 的触发源头在属性的convert函数里。以inline为例ArgParser::List分支第一步就是let l cx.expect_single(list)?;inline.rs L40-L41列表为空 →ExpectedArgument→ E0805列表有 2 个以上元素 →ExpectedSingleArgument→ E0805只有列表里恰好 1 个元素时才会继续匹配always/never关键字。各属性的convert函数是同类写法的集合阅读对应属性的解析源码compiler/rustc_attr_parsing/src/attributes/目录即可确认它对参数个数的精确要求。实操排查清单遇到error[E0805]时建议按以下顺序处理读诊断标签expected an argument here缺参数还是expected a single argument here多参数这直接决定你该“补一个”还是“删到只剩一个”。利用诊断自带的 helpmust be of the form ...一行会给出该属性的标准形例如cfg!(predicate)多数情况下照抄即可。核对属性模板的合法形态常见如#[inline]/#[inline(always)]/#[inline(never)]三选一不可同时出现cfg!(...)括号内是谓词而非常量布尔表达式外的裸标识符。区分相邻错误码如果诊断标题仍是malformed ... input但错误码是 E0539 或 E0565说明问题不在“个数”而在“形态”该是列表却给了 namevalue或该无参数却给了参数参见 E0539.md。对照 UI 测试仓库tests/ui/下存在大量预期含 E0805 的.stderr文件可直接检索比对同类写法在编译器各版本中的预期行为。小结E0805 是 rustc 属性解析器针对“恰好需要 1 个参数”约束的专用错误码参数缺失报“expected an argument here”参数多于 1 个报“expected a single argument here”两者都从 E0539 基础诊断升级而来。官方文档以#[inline()]与#[inline(always, never)]两个反例说明了触发条件修复原则就是让参数个数匹配属性模板——不给参数#[inline]或恰好给一个#[inline(always)]。结合 diagnostics.rs 的分支逻辑 与 各属性的 convert 实现你可以快速判断任何内置属性的合法参数形式而不是只能靠试错。【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考