From 8b6c36d24fe9d49f9ed6a5c722ab2cd41a7c7c08 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 2 Oct 2026 22:44:34 +0800 Subject: [PATCH] =?UTF-8?q?feat(match):=20=E9=87=8D=E5=90=8D=20case=20?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=20fail-fast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HandlesMatch._HandleMatchLlvm 新增前置检查(在产出任何 IR 之前):新增 _CaseLabelKey 提取 case 的 switch 标签(MatchValue 值 / MatchSingleton(None) / MatchClass 变体名 / MatchOr 组合),标签重复或出现多个 `case _` 时报 FailFastError, 并给出重复的 case 序号与标签键(C switch 不允许重复 case 标签)。 --- lib/core/Handles/HandlesMatch.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/core/Handles/HandlesMatch.py b/lib/core/Handles/HandlesMatch.py index 21ba577..ecca046 100644 --- a/lib/core/Handles/HandlesMatch.py +++ b/lib/core/Handles/HandlesMatch.py @@ -36,6 +36,27 @@ class MatchHandle(BaseHandle): def _HandleMatchLlvm(self, Node: ast.Match) -> None: Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + # 重名 case 检测(fail-fast):C 的 switch 不允许重复 case 标签——重复标签会让 + # 某个臂永远不可达,且通常意味着漏改的分支;`case _`(default)同样只允许一个。 + # 在产出任何 IR 之前检查,保证报错即终止。 + SeenLabels: dict[str, int] = {} + DefaultCount: int = 0 + for ci, case in enumerate(Node.cases): + Key: str | None = MatchHandle._CaseLabelKey(case.pattern) + if Key is None: + if isinstance(case.pattern, ast.MatchAs) and case.pattern.pattern is None: + DefaultCount += 1 + continue + if Key in SeenLabels: + from lib.core.LLVMCG.FuncGen import FailFastError + raise FailFastError( + f"match 出现重名 case:标签 '{Key}' 已在第 {SeenLabels[Key]} 个 case 使用," + f"第 {ci} 个 case 重复(C switch 不允许重复 case 标签)") + SeenLabels[Key] = ci + if DefaultCount > 1: + from lib.core.LLVMCG.FuncGen import FailFastError + raise FailFastError( + f"match 出现 {DefaultCount} 个 `case _`(default 只允许一个)") SubjectVal: ir.Value | None = self.HandleExprLlvm(Node.subject) if not SubjectVal: return