From 5993affd9c20624303b39123e16f06bd275d992b Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 7 Oct 2026 14:35:25 +0800 Subject: [PATCH] =?UTF-8?q?fix(type):=20const=20=E7=AD=89=E9=99=90?= =?UTF-8?q?=E5=AE=9A=E8=81=94=E5=90=88=E4=B8=8D=E5=86=8D=E8=A2=AB=E8=AF=AF?= =?UTF-8?q?=E5=88=A4=E4=B8=BA=20str*/bytes*?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _is_ptr_element_annotation 原先只要注解联合里出现 str/bytes 就返回 1(按 i8** 处理, 8 字节元素步长),于是 const str(t.CConst | str,实际仍是 i8*)的下标取到的是指针。 现在要求联合必须带 CPtr 标记(真正的 str*/bytes*)才判定;模块级全局的同一处逻辑 (TranslatorGenMixin)同步收紧。新增 _annotation_has_cptr_marker 供两处复用。 复现:def F(p: str) -> int: / path: const str = p / ch: char = path[i] -> CastError 指针转整数(形参位置的 const str 一直正常,仅局部/全局错) --- App/lib/core/Gen/AssignGenMixin.vp | 26 ++++++++++++++++++++++++-- App/lib/core/Gen/TranslatorGenMixin.vp | 5 +++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 4375b13..424f376 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -517,6 +517,24 @@ novirtual class AssignGenMixin: if self._annotation_contains_name(bop.right, name) != 0: return 1 return 0 + def _annotation_has_cptr_marker(self, annot: ast.AST*) -> int: + """Return 1 if the annotation union carries a CPtr marker (the star form ` | t.CPtr`).""" + if annot is None: return 0 + k: int = annot.kind() + if k == ast.ASTKind.Attribute: + at: ast.Attribute* = ast.Attribute*(annot) + if at.attr is not None and string.strcmp(at.attr, "CPtr") == 0: return 1 + return 0 + if k == ast.ASTKind.Name: + nm: ast.Name* = ast.Name*(annot) + if nm.id is not None and string.strcmp(nm.id, "CPtr") == 0: return 1 + return 0 + if k == ast.ASTKind.BinOp: + bop: ast.BinOp* = ast.BinOp*(annot) + if self._annotation_has_cptr_marker(bop.left) != 0: return 1 + if self._annotation_has_cptr_marker(bop.right) != 0: return 1 + return 0 + # _is_ptr_element_annotation - check whether an annotation is bytes* or str* # bytes*/str* => 8-byte element stride (i8**); char*/int8* => 1-byte stride. def _is_ptr_element_annotation(self, annot: ast.AST*) -> int: @@ -526,8 +544,12 @@ novirtual class AssignGenMixin: if k != ast.ASTKind.BinOp: return 0 bop: ast.BinOp* = ast.BinOp*(annot) if bop.op != ast.OpKind.BitOr: return 0 - if self._annotation_contains_name(annot, "str") != 0: return 1 - if self._annotation_contains_name(annot, "bytes") != 0: return 1 + # str/bytes are already i8*; only the union WITH a pointer marker (str*/bytes*) is i8** and + # needs 8-byte element slots. A union that merely carries them (e.g. `const str`, which is + # t.CConst | str and stays i8*) must keep the 1-byte stride. + if self._annotation_has_cptr_marker(annot) != 0: + if self._annotation_contains_name(annot, "str") != 0: return 1 + if self._annotation_contains_name(annot, "bytes") != 0: return 1 # Generic type param / nested union | t.CPtr: scalars use their own size, pointers use 8-byte slots if self._is_generic_tp_or_nested(bop.left) != 0 or self._is_generic_tp_or_nested(bop.right) != 0: gp_nm: str = None diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index 7fc7df0..6a0d8f2 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -859,8 +859,9 @@ novirtual class TranslatorGenMixin: if aa_ml.annotation.kind() == ast.ASTKind.BinOp: bop_ml: ast.BinOp* = ast.BinOp*(aa_ml.annotation) if bop_ml.op == ast.OpKind.BitOr: - if self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "str") != 0 or self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "bytes") != 0: - self.Gen.VarGen.set_var_ptr_element(trans.SymTab, var_name) + if self.Gen.AssignGen._annotation_has_cptr_marker(aa_ml.annotation) != 0: + if self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "str") != 0 or self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "bytes") != 0: + self.Gen.VarGen.set_var_ptr_element(trans.SymTab, var_name) return 1 return 0