ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Rust 编译错误 E0586 解析:inclusive range(闭区间)缺少终点时的报错原因与修复

Rust 编译错误 E0586 解析:inclusive range(闭区间)缺少终点时的报错原因与修复 Rust 编译错误 E0586 解析inclusive range闭区间缺少终点时的报错原因与修复【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust导读E0586 是 rustc 编译器在源码中出现..inclusive range / 闭区间语法但**没有提供终点end**时报告的错误。它常见于对数组或Vec进行切片索引如tmp[1..]也可能在match范围模式等位置出现。阅读完本文你将掌握该错误的确切触发条件、三种修复思路以及 rustc 语法解析阶段如何定位并生成这条诊断信息含可直接跳转阅读的源码依据。一、错误现象..之后必须要有终点在 Rust 中范围表达式共有四种形态其中只有三种允许省略一侧边界语法含义是否允许省略终点a..b半开区间含a不含b可省略为a..RangeFroma..b闭区间同时包含a与b不允许省略即触发 E0586..b/..bRangeTo / RangeToInclusive用于索引的快捷写法对..b同样必须给出b..全范围—..的字面语义是“把右侧的终点也包含进来”因此编译器在解析时严格要求它后面必须存在一个结束表达式。一旦写成1..这种“有起点、有等号、没有终点”的形式rustc 就会报告 E0586。E0586 错误文档 给出了最典型的出错代码fn main() { let tmp vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; let x tmp[1..]; // error: inclusive range was used with no end }这里意图是“从下标 1 切到末尾”但..要求写出要包含的末下标于是1..成为一个没有终点的非法闭区间。二、两种标准修复方式方案一改用不含终点语义的..推荐如果你想要的是“只给起点、不要终点”那语义对应的是半开区间而非闭区间把..换成..即可fn main() { let tmp vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; let x tmp[1..]; // ok! 从下标 1 切到末尾 }方案二为闭区间补上明确的终点如果你确实想使用闭区间就把终点写出来fn main() { let tmp vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; let x tmp[1..3]; // ok! 取下标 1..3即 1、2、3 三个元素 }方案一更贴近多数“切到末尾”的真实意图方案二适用于需要精确表达“包含第 N 个元素”的边界计算例如把最后一个元素一并取出的tmp[..len - 1]场景。三、从源码看 rustc 是如何报出 E0586 的该错误并非发生在类型检查或代码生成阶段而是在语法解析parse阶段就已被识别并拦截。1. 诊断结构的定义在 rustc_parse 的诊断定义文件 中可以找到与 E0586 一一对应的诊断结构#[derive(Diagnostic)] #[diag(inclusive range with no end, code E0586)] #[note(inclusive ranges must be bounded at the end (..b or a..b))] pub(crate) struct InclusiveRangeNoEnd { #[primary_span] #[suggestion( use .. instead, code .., applicability machine-applicable, style verbose )] pub span: Span, }值得注意的细节它的#[note]进一步解释了设计约束闭区间必须在末端有界合法形态只能是..b或a..b它自带一条machine-applicable的机器可应用建议把..替换为..这正是 IDE 与cargo fix能自动给出“use..instead”提示的机制来源错误主 span 指向出错的..语法本身便于在源码中高亮定位。2. 表达式场景的触发点对表达式包括tmp[1..]这种索引表达式而言触发路径位于 rustc_parse 的 mk_range 方法fn mk_range( mut self, start: OptionBoxExpr, end: OptionBoxExpr, limits: RangeLimits, ) - ExprKind { if end.is_none() limits RangeLimits::Closed { let guar self.inclusive_range_with_incorrect_end(); ExprKind::Err(guar) } else { ExprKind::Range(start, end, limits) } }可以看到当解析器发现这是一个Closed..范围、且end 为空时就调用inclusive_range_with_incorrect_end()生成诊断并把该表达式降级为ExprKind::Err从而让编译流程继续运行、尽可能多地报告其他错误。inclusive_range_with_incorrect_end的实现位于 compiler/rustc_parse/src/parser/pat.rs#L1379-L1405。它并非对所有“缺终点”的情况一概报 E0586而是会先区分用户到底敲错了什么如果..后面紧跟即敲成了..报告InclusiveRangeExtraEquals提示“inclusive ranges end with a single equals sign (..)”如果在match臂中..与紧贴如X.. expr..被连读报告InclusiveRangeMatchArrow建议写成X.. expr并补空格其余情况才落入默认分支即第 1403 行调用self.dcx().emit_err(InclusiveRangeNoEnd { span })——这就是 E0586 的实际发射点。编译器在此处“假定用户本意是半开区间..”从而给出替换建议与本文第一节的修复方案一完全一致。3. 模式pattern场景同样受约束同一个inclusive_range_with_incorrect_end方法也被范围模式解析复用。在 parse_pat_range_begin_with 中当用户写出形如X..但后续没有可解析的终点时对应第 1370-1373 行if let RangeEnd::Included(_) re.node { // FIXME(Centril): Consider semantic errors instead in ast_validation. self.inclusive_range_with_incorrect_end(); }也就是说在match等位置写1.. ...本意1.. ...之类的范围模式时同样会走这条诊断逻辑——只是若紧跟着会优先命中前面提到的InclusiveRangeMatchArrow提示添加空格从而给出比 E0586 更贴合上下文的提示。4. 历史遗留语法...的旁证顺带一提Rust 早年的“包含式范围”曾用...表示。解析器在遇到...时会给出单独的DotDotDot诊断其 suggestion 列表 会同时建议“use..for an exclusive range”或“or..for an inclusive range”帮助旧代码迁移到现代语义。这也反向说明..是当前闭区间唯一的标准书写它的终点不可省略否则语义上无法自洽。四、小结与自查清单E0586 的本质是一条例行性parse-time语法约束错误而非类型错误。遇到它时按以下顺序自查即可快速修复看意图若想“只取起点到末尾”把..换成..看边界若确实要闭区间补全终点如1..3看上下文若错误出现在match臂中且提示与相关通常是..与箭头连写加一个空格分隔即可。Rust 编辑器工具链基于 rust-analyzer与cargo fix之所以能自动提供替换建议正是因为在 InclusiveRangeNoEnd 诊断结构 中标注了machine-applicable的..替换。理解这条诊断背后的“闭区间必须有界”设计约束也能帮助你在阅读涉及 Range、RangeInclusive 的标准库索引代码时更快地判断边界写法是否合法。【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表