fix(includes): 槽视图改为 cast 到声明类型(地址 → 二级指针不再隐式转换)

【类别 c 源码违规】`slot: <A> = 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。
This commit is contained in:
TermiNexus committed 2026-09-29 15:10:33 +08:00
1 parent db47b92983
commit 0212bd942c
5 files changed
+27 -27

No files matched your search

+6 -6
View File
@@ -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)