diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index af74153..8eccb34 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -856,51 +856,36 @@ class AssignHandle(BaseHandle): FuncPtrI8: ir.Value = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"func_ptr_i8_{AttrName}") Gen._store(FuncPtrI8, MethodPtrAddr) return - # 自指针的 pointee 可能是**另一份同名 struct 实例**:函数签名里那份 - # 仍 opaque(`_get_or_create_struct` 早期创建、从未 set_body),而类键 - # `Gen.structs[ClassName]` 上那份已具化。typed pointer 的 GEP 必须在 - # 编译期算出元素类型 ⇒ 走 opaque pointee 时 llvmlite 在 - # `types.py:633 self.elements[i.constant]` 抛裸 TypeError - # ('NoneType' object is not subscriptable;现场:astaux.vp - # `Keyword.__init__` 的 `self.arg = _copy_str(pool, arg)`)。 - # 修法:先 bitcast 到**有 body 的那份实例**,再把该实例作为 - # StructHint 交给 `_get_member_offset` —— 偏移与 GEP 必须同源 - # (与属性读取路径 _gep_and_Load_member 的 415916b3 同口径)。 - _SelfPointee: ir.Type | None = None - if isinstance(SelfPtr.type, ir.PointerType): - _SelfPointee = SelfPtr.type.pointee - struct_type: ir.Type = Gen.structs[ClassName] - if (isinstance(_SelfPointee, ir.IdentifiedStructType) - and _SelfPointee.elements is None - and isinstance(struct_type, ir.IdentifiedStructType) - and struct_type.elements is not None): - SelfPtr = Gen.builder.bitcast( - SelfPtr, ir.PointerType(struct_type), - name=f"concrete_self_{ClassName}") - _SelfPointee = struct_type - # 孪生体搜索(治本,2026-09-30):类键实例可能**也是** opaque —— 同一类名 - # 常有两份 struct 实例(短名 'Keyword' / sha1 全名 '.Keyword'), - # 函数签名里的 self 用哪一份、StructGen 具化的是哪一份**并不保证一致**。 - # 现场:includes/ast/astaux.vp:165 `self.arg = _copy_str(pool, arg)` 的 - # 基址 pointee 是 opaque 的 `%".Keyword"*`,GEP 无法在编译期算元素类型。 - # 修法:按**同短名**取一份已具化实例(工具函数 _FindConcreteTwin,读路径 - # HandlesExprAttr 共用同一判据)并 bitcast —— 偏移与 GEP 由此同源。 - # 找不到 ⇒ 保持现状,交由 RequirePointerOperand 的 opaque 守卫 fail-fast - # (报出同短名实例清单,暴露"body 从未 set_body"),**不静默兜底**。 + # 自指针基址收口:与**读路径同一判据源**(HandlesExprAttr + # `_ConcretizeGepBase` / `_ConcretePointeeFor`),三步同源: + # ① 类键那份 opaque ⇒ 先 `_TryLoadStructFromStub` 补 body; + # ② 仍不可用 ⇒ 按同短名取一份已具化实例(`_FindConcreteTwin`); + # ③ 都拿不到 ⇒ 原样返回,由下方 opaque fail-fast 报根因。 + # 写路径此前是**内联**版本、缺 ①:类键那份仍 opaque 且 `Gen.structs` + # 里也还没有孪生体时(body 只在 stub 文件里待加载),内联版会一路走到 + # GEP 撞 opaque(现场 2026-09-30:includes/ast/astaux.vp:165 + # `self.arg = _copy_str(pool, arg)` 的基址 pointee 是 opaque 的 + # %"8312ce86a2fd82c0.Keyword"*,而同短名 'Keyword' 键那份已具化 10 槽)。 + # 偏移与 GEP 必须同源:返回的实例同时作为 `_get_member_offset` 的 StructHint。 + SelfPtr, _SelfPointee = self.Trans.ExprAttrHandle._ConcretizeGepBase( + Gen, SelfPtr, ClassName, f"concrete_self_{ClassName}") + struct_type: ir.Type = (_SelfPointee + if isinstance(_SelfPointee, ir.IdentifiedStructType) + else Gen.structs[ClassName]) if (isinstance(_SelfPointee, ir.IdentifiedStructType) and _SelfPointee.elements is None): - _Twin: ir.IdentifiedStructType | None = Gen._FindConcreteTwin(_SelfPointee) - if _Twin is None: - try: - _Twin = Gen._FindConcreteTwin(Gen.structs.get(ClassName)) - except Exception: - _Twin = None - if _Twin is not None: - SelfPtr = Gen.builder.bitcast( - SelfPtr, ir.PointerType(_Twin), - name=f"concrete_twin_self_{ClassName}") - _SelfPointee = _Twin - struct_type = _Twin + # 收口失败:类键那份、同短名孪生体、以及 `_TryLoadStructFromStub` + # 三条路都没拿到 body。**不得**再落回下方 `offset >= max_offset` + # 的「存回临时变量」分支 —— 该临时变量不在对象布局里,后续 + # `self.attr` 读路径按 GEP 取值,写入会被**静默丢弃**。此处 fail-fast。 + from lib.core.LLVMCG.FuncGen import FailFastError as _FFE0 + raise _FFE0( + f"属性写入 '{ClassName}.{AttrName}' 的 self 基址指向**未具化**" + f"结构体:'{getattr(_SelfPointee, 'name', '?')}'(opaque)。" + f"已尝试:类键 {ClassName!r} 的实例 → 同短名孪生体 → " + f"_TryLoadStructFromStub 补 body,均未拿到 elements。" + f"请查该类 body 为何从未 set_body(StructGen._generate_structs)。" + + (f"\n {Gen._get_node_info()}" if hasattr(Gen, '_get_node_info') else "")) offset: int = Gen._get_member_offset(AttrName, ClassName, _SelfPointee) max_offset: int = (len(struct_type.elements) if isinstance(struct_type, ir.IdentifiedStructType)