fix(type): 数组退让豁免提到级数检查之前,修 [N]str 形参被误判 CastError

形参侧 CArray 按 C 语义退让成元素指针 str*(级数 2),实参仍是 [N]str 的数组地址(级数 1)→ _ptr_cast_reason 先查级数就判 PC_DEPTH,_pointee_convert_reason 里那条既有数组退让豁免成了死代码。元素为 i8 时级数不变所以一直没暴露,元素本身是指针才炸(现场:includes/tomllib _parse_key_path 的 segs)。
This commit is contained in:
TermiNexus committed 2026-10-08 20:03:42 +08:00
1 parent 1dd53ebff5
commit 934708b206
1 file changed
+7
+7
View File
@@ -400,6 +400,13 @@ novirtual class ExprGenBase:
slev: int = self.get_ptr_level(src_ty)
dlev: int = self.get_ptr_level(dst_ty)
if slev == 0 or dlev == 0: return PC_OK
# 豁免 0(必须放在级数检查**之前**):固定数组退让 `[N]T* -> T*`(C 语义:数组名退让成
# 首元素指针)。元素是 i8 时级数不变(1→1,恰好由"全类型指针通配"放行),但元素本身
# 是指针时级数会 +1(`[N]str` -> `str*` 即 `Ptr([N]i8*) -> Ptr(i8*)`:1→2),
# 级数检查会先判成 PC_DEPTH,使下面 _pointee_convert_reason 里那条既有豁免永远够不到
# (死代码)。现场:includes/tomllib `_parse_key_path(s, segs: [N]str, cap)` —— 形参按
# C 语义退让成 `str*`(FuncGenDef 的 Array 形参退让),实参仍是 `[N]str` 的数组地址。
if self._is_array_decay(pool, src_ty.Pointee, dst_ty.Pointee) != 0: return PC_OK
# Different depth: forbidden regardless of pointee.
if slev != dlev: return PC_DEPTH
# Rule 4: identical types (same depth and pointee) are not a conversion.