From 0212bd942c29c9b92466155f0078c08cc7714969 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 29 Sep 2026 15:07:17 +0800 Subject: [PATCH] =?UTF-8?q?fix(includes):=20=E6=A7=BD=E8=A7=86=E5=9B=BE?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20cast=20=E5=88=B0=E5=A3=B0=E6=98=8E?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=EF=BC=88=E5=9C=B0=E5=9D=80=20=E2=86=92=20?= =?UTF-8?q?=E4=BA=8C=E7=BA=A7=E6=8C=87=E9=92=88=E4=B8=8D=E5=86=8D=E9=9A=90?= =?UTF-8?q?=E5=BC=8F=E8=BD=AC=E6=8D=A2=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 【类别 c 源码违规】`slot: = t.CPtr(addr)` 把一级指针(i8*)隐式塞进二级注解 (i8** / X**),违反 2026-09-28 收紧的「指针级数必须相同」。TransPyV 侧 coerce 没有「值侧是显式 cast」豁免(ExprGenBase._ptr_cast_reason 先比层数),故回归测试 在 includes/llvmlite/__function.vp:950 首爆: 指针隐式转指针已禁止:指针层数不同(源 1 级 → 目标 2 级);源类型 i8* → 目标 i8**。 判据(按注解层数分类,不枚举调用点): · str / bytes 本身即 i8*(含一层),再 | t.CPtr ⇒ i8**(槽里存的是 str) · str* / bytes* 同 str | t.CPtr(i8**) · T | t.CPtr:T 为指针特化时 ⇒ X**(如 list[X*]、list[str]) · A | t.CPtr | t.CPtr:逐层叠加 ⇒ 二级(如 hashtable 的 value 槽) 一级注解(int | t.CPtr = i32*、t.CUInt64T | t.CPtr = i64*、类名 | t.CPtr = X*) 与 i8* 同级且 i8* 是通用指针通配 ⇒ 本可编译,一律保持原样不动。 修法:RHS 改为**cast 到声明类型**,即「注解写什么就 cast 什么」—— `t.CPtr(addr)` / `(t.CPtr)(addr)` / `rawptr(addr)` → `(A)(addr)`; `str*` 注解沿用 sys.vp 既有写法 `str*(addr)`(等价于 `str | t.CPtr` 强转)。 显式写明目标类型后,层数与被指类型均由程序员给出,编译器无需任何豁免。 与 TransPyV/App CallGenCBuiltin.vp 的 `cl_ptr: str | t.CPtr = (str | t.CPtr)(cl_addr)` 以及 includes/vector.vp 的 `dst: T* = (T*)offset` 同一写法。 本仓改动 27 处 / 5 文件: _list.vp 7 _dict.vp 9(8 处槽视图 + L63 的 `key_ptr: str* = rawptr(...)`) hashtable.vp 6(含 3 处 …|t.CPtr|t.CPtr) llvmlite/__function.vp 2 mlirlite/__function.vp 3(2 处槽视图 + _mlir_slotp 的 return:该函数返回注解 即 str | t.CPtr,其 return 同属「i8* → 二级」) 未动其它一级注解站点,例如 _dict.vp 的 int/float/t.CDouble/t.CInt | t.CPtr、 hashtable.vp 的 t.CUInt64T | t.CPtr、argparse.vp:168 的 Argument | t.CPtr。 --- _dict.vp | 18 +++++++++--------- _list.vp | 14 +++++++------- hashtable.vp | 12 ++++++------ llvmlite/__function.vp | 4 ++-- mlirlite/__function.vp | 6 +++--- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/_dict.vp b/_dict.vp index 451bf95..329e8bc 100644 --- a/_dict.vp +++ b/_dict.vp @@ -60,7 +60,7 @@ class dict: def _find(self, key: str) -> sizet: """Find index of target key; returns __count__ if not found""" for i in range(self.__count__): - key_ptr: str* = rawptr(uint64(self.__keys__) + i * 8) + key_ptr: str* = str*(uint64(self.__keys__) + i * 8) if string.strcmp(key_ptr[0], key) == 0: return i return self.__count__ @@ -70,7 +70,7 @@ class dict: idx: sizet = self._find(key) if idx >= self.__count__: return None # Variant.ptr is located at offset 8 within Variant structure - val_ptr: str | t.CPtr = t.CPtr(uint64(self.__values__) + idx * _VARIANT_SIZE + 8) + val_ptr: str | t.CPtr = (str | t.CPtr)(uint64(self.__values__) + idx * _VARIANT_SIZE + 8) return val_ptr[0] def __setitem__(self, key: str, val: t.CNeedPtr): @@ -86,7 +86,7 @@ class dict: # Update existing key vtype_ptr: t.CInt | t.CPtr = t.CPtr(uint64(self.__values__) + idx * _VARIANT_SIZE) vtype_ptr[0] = vtype - val_ptr: str | t.CPtr = t.CPtr(uint64(self.__values__) + idx * _VARIANT_SIZE + 8) + val_ptr: str | t.CPtr = (str | t.CPtr)(uint64(self.__values__) + idx * _VARIANT_SIZE + 8) val_ptr[0] = ptr return if self.__count__ >= self.__capacity__: @@ -99,11 +99,11 @@ class dict: self.__keys__ = new_keys self.__values__ = new_values self.__capacity__ = new_cap - key_ptr: str | t.CPtr = t.CPtr(uint64(self.__keys__) + self.__count__ * 8) + key_ptr: str | t.CPtr = (str | t.CPtr)(uint64(self.__keys__) + self.__count__ * 8) key_ptr[0] = key vtype_ptr: t.CInt | t.CPtr = t.CPtr(uint64(self.__values__) + self.__count__ * _VARIANT_SIZE) vtype_ptr[0] = vtype - val_ptr: str | t.CPtr = t.CPtr(uint64(self.__values__) + self.__count__ * _VARIANT_SIZE + 8) + val_ptr: str | t.CPtr = (str | t.CPtr)(uint64(self.__values__) + self.__count__ * _VARIANT_SIZE + 8) val_ptr[0] = ptr self.__count__ += 1 @@ -168,7 +168,7 @@ class dict: idx: sizet = self._find(key) if idx >= self.__count__: return default - val_ptr: str | t.CPtr = t.CPtr(uint64(self.__values__) + idx * _VARIANT_SIZE + 8) + val_ptr: str | t.CPtr = (str | t.CPtr)(uint64(self.__values__) + idx * _VARIANT_SIZE + 8) return val_ptr[0] def contains(self, key: str) -> t.CInt: @@ -187,7 +187,7 @@ class dict: raise StopIteration idx: sizet = self.__iter_index__ self.__iter_index__ = idx + 1 - key_ptr: str | t.CPtr = t.CPtr(uint64(self.__keys__) + idx * 8) + key_ptr: str | t.CPtr = (str | t.CPtr)(uint64(self.__keys__) + idx * 8) return key_ptr[0] # ============================================================ @@ -200,9 +200,9 @@ class dict: obj: rawptr[json.JsonValue] = json.object(pool) i: sizet = 0 while i < self.__count__: - key_ptr: str | t.CPtr = t.CPtr(uint64(self.__keys__) + i * 8) + key_ptr: str | t.CPtr = (str | t.CPtr)(uint64(self.__keys__) + i * 8) vtype_ptr: t.CInt | t.CPtr = t.CPtr(uint64(self.__values__) + i * _VARIANT_SIZE) - val_ptr: str | t.CPtr = t.CPtr(uint64(self.__values__) + i * _VARIANT_SIZE + 8) + val_ptr: str | t.CPtr = (str | t.CPtr)(uint64(self.__values__) + i * _VARIANT_SIZE + 8) vt: t.CInt = vtype_ptr[0] vp: t.CPtr = val_ptr[0] jv: rawptr[json.JsonValue] = json.null(pool) diff --git a/_list.vp b/_list.vp index 0c881df..fc7dfdd 100644 --- a/_list.vp +++ b/_list.vp @@ -57,29 +57,29 @@ class list[T]: string.memcpy(new_data, self.__data__, self.__count__ * self.__elem_size__) self.__data__ = new_data self.__capacity__ = new_cap - elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + self.__count__ * self.__elem_size__) + elem_ptr: T | t.CPtr = (T | t.CPtr)(t.CUInt64T(self.__data__) + self.__count__ * self.__elem_size__) elem_ptr[0] = item self.__count__ += 1 def get(self, index: sizet) -> T: - elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + index * self.__elem_size__) + elem_ptr: T | t.CPtr = (T | t.CPtr)(t.CUInt64T(self.__data__) + index * self.__elem_size__) return elem_ptr[0] def __getitem__(self, index: sizet) -> T: - elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + index * self.__elem_size__) + elem_ptr: T | t.CPtr = (T | t.CPtr)(t.CUInt64T(self.__data__) + index * self.__elem_size__) return elem_ptr[0] def set(self, index: sizet, value: T): - elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + index * self.__elem_size__) + elem_ptr: T | t.CPtr = (T | t.CPtr)(t.CUInt64T(self.__data__) + index * self.__elem_size__) elem_ptr[0] = value def __setitem__(self, index: sizet, value: T): - elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + index * self.__elem_size__) + elem_ptr: T | t.CPtr = (T | t.CPtr)(t.CUInt64T(self.__data__) + index * self.__elem_size__) elem_ptr[0] = value def pop(self) -> T: self.__count__ -= 1 - elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + self.__count__ * self.__elem_size__) + elem_ptr: T | t.CPtr = (T | t.CPtr)(t.CUInt64T(self.__data__) + self.__count__ * self.__elem_size__) return elem_ptr[0] def clear(self): @@ -94,5 +94,5 @@ class list[T]: raise StopIteration idx: sizet = self.__iter_index__ self.__iter_index__ = idx + 1 - elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + idx * self.__elem_size__) + elem_ptr: T | t.CPtr = (T | t.CPtr)(t.CUInt64T(self.__data__) + idx * self.__elem_size__) return elem_ptr[0] diff --git a/hashtable.vp b/hashtable.vp index 6b486ae..ab5a3f5 100644 --- a/hashtable.vp +++ b/hashtable.vp @@ -74,7 +74,7 @@ class HashTable: def _slot_key(self, idx: sizet) -> str: """Read key pointer from target slot.""" - ptr: str | t.CPtr = t.CPtr(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 8) + ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 8) return ptr[0] def _slot_value(self, idx: sizet) -> t.CPtr: @@ -83,17 +83,17 @@ class HashTable: # 故 t.CUInt64T|t.CPtr|t.CPtr = Ptr(Ptr(i64)) = i64**,取下标得 i64*(指针), # 与返回类型 t.CPtr(i8*)同级指针可隐式 bitcast。若只写 t.CUInt64T|t.CPtr # (= i64*,存哈希整数用),取下标得标量 i64 → 撞「整数隐式转指针禁止」。 - ptr: t.CUInt64T | t.CPtr | t.CPtr = t.CPtr(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 16) + ptr: t.CUInt64T | t.CPtr | t.CPtr = (t.CUInt64T | t.CPtr | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 16) return ptr[0] def _set_slot(self, idx: sizet, h: t.CUInt64T, key: str, val: t.CPtr): """Assign three fields of the target slot.""" h_ptr: t.CUInt64T | t.CPtr = t.CPtr(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE) h_ptr[0] = h - k_ptr: str | t.CPtr = t.CPtr(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 8) + k_ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 8) k_ptr[0] = key # 同 _slot_value:value 槽按「指针的指针」(i64**) 注解,元素才是指针 - v_ptr: t.CUInt64T | t.CPtr | t.CPtr = t.CPtr(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 16) + v_ptr: t.CUInt64T | t.CPtr | t.CPtr = (t.CUInt64T | t.CPtr | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 16) v_ptr[0] = val def _find_slot(self, key: str, h: t.CUInt64T) -> sizet: @@ -142,9 +142,9 @@ class HashTable: old_h_ptr: t.CUInt64T | t.CPtr = t.CPtr(t.CUInt64T(old_slots) + i * _HT_SLOT_SIZE) h: t.CUInt64T = old_h_ptr[0] if h != _HT_EMPTY and h != _HT_TOMBSTONE: - old_k_ptr: str | t.CPtr = t.CPtr(t.CUInt64T(old_slots) + i * _HT_SLOT_SIZE + 8) + old_k_ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(old_slots) + i * _HT_SLOT_SIZE + 8) # 同 _slot_value:value 槽按「指针的指针」(i64**) 注解,元素才是指针 - old_v_ptr: t.CUInt64T | t.CPtr | t.CPtr = t.CPtr(t.CUInt64T(old_slots) + i * _HT_SLOT_SIZE + 16) + old_v_ptr: t.CUInt64T | t.CPtr | t.CPtr = (t.CUInt64T | t.CPtr | t.CPtr)(t.CUInt64T(old_slots) + i * _HT_SLOT_SIZE + 16) k: str = old_k_ptr[0] v: t.CPtr = old_v_ptr[0] idx: sizet = self._find_slot(k, h) diff --git a/llvmlite/__function.vp b/llvmlite/__function.vp index c557750..0495ea8 100644 --- a/llvmlite/__function.vp +++ b/llvmlite/__function.vp @@ -947,7 +947,7 @@ def _peephole_opt(func: rawptr[Function], pool: memhub.MemBuddy*): if lname is not None: string.strncpy(lname, ls + 1, lname_len - 1) lname[lname_len - 1] = '\0' - slotp: str | t.CPtr = t.CPtr(t.CUInt64T(load_ltoks) + load_cnt * 8) + slotp: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(load_ltoks) + load_cnt * 8) slotp[0] = lname load_cnt += 1 if blk_s == entry_blk and st_line_order < 0: @@ -992,7 +992,7 @@ def _peephole_opt(func: rawptr[Function], pool: memhub.MemBuddy*): safe_len: sizet = string.strlen(safe_val) li2: int = 0 while li2 < load_cnt: - slotsp: str | t.CPtr = t.CPtr(t.CUInt64T(load_ltoks) + li2 * 8) + slotsp: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(load_ltoks) + li2 * 8) ltok: str = slotsp[0] if ltok is not None: # ltok 在该 load 名的全函数行扫描中不变,strlen 只求一次 diff --git a/mlirlite/__function.vp b/mlirlite/__function.vp index 0e5cef2..fbdc471 100644 --- a/mlirlite/__function.vp +++ b/mlirlite/__function.vp @@ -959,7 +959,7 @@ def _peephole_opt(func: rawptr[Function], pool: memhub.MemBuddy*): if lname is not None: string.strncpy(lname, ls + 1, lname_len - 1) lname[lname_len - 1] = '\0' - slotp: str | t.CPtr = t.CPtr(t.CUInt64T(load_ltoks) + load_cnt * 8) + slotp: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(load_ltoks) + load_cnt * 8) slotp[0] = lname load_cnt += 1 if blk_s == entry_blk and st_line_order < 0: @@ -1004,7 +1004,7 @@ def _peephole_opt(func: rawptr[Function], pool: memhub.MemBuddy*): safe_len: sizet = string.strlen(safe_val) li2: int = 0 while li2 < load_cnt: - slotsp: str | t.CPtr = t.CPtr(t.CUInt64T(load_ltoks) + li2 * 8) + slotsp: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(load_ltoks) + li2 * 8) ltok: str = slotsp[0] if ltok is not None: # ltok 在该 load 名的全函数行扫描中不变,strlen 只求一次 @@ -1197,7 +1197,7 @@ _SC_Buf: str = None def _mlir_slotp(buf: t.CPtr, idx: int) -> str | t.CPtr: """表格槽位地址(buf + idx*8)""" - return t.CPtr(t.CUInt64T(buf) + idx * 8) + return (str | t.CPtr)(t.CUInt64T(buf) + idx * 8) def _mlir_dup(s: str) -> str: