From 6073f603210fdd9ca3255ced5b8a78289b3a040a Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 3 Nov 2026 17:21:35 +0800 Subject: [PATCH] fix(own): read nullability through the own wrapper `own (T?)` resolves to the nullable pointer, so a `None` initializer is valid there. --- App/lib/core/Gen/GenApi.vp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index 63641f9..44a49fb 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -130,14 +130,21 @@ def strict_obs() -> int: # annotation_is_nullable - 1 when a type annotation carries the `?` suffix (`NullableT[T]`). +# `own` keeps an existing pointer layer, so it is transparent for nullability: `own (T?)` is nullable. def annotation_is_nullable(ann: ast.AST*) -> int: - if ann is None or ann.kind() != ast.ASTKind.Subscript: return 0 - sb: ast.Subscript* = ast.Subscript*(ann) - if sb.value is None or sb.value.kind() != ast.ASTKind.Name: return 0 - nm: ast.Name* = ast.Name*(sb.value) - if nm.id is None: return 0 - if string.strcmp(nm.id, "OptionT") == 0: return 1 - if string.strcmp(nm.id, "NullableT") == 0: return 1 + node: ast.AST* = ann + depth: int = 0 + while node is not None and depth < 8: + if node.kind() != ast.ASTKind.Subscript: return 0 + sb: ast.Subscript* = ast.Subscript*(node) + if sb.value is None or sb.value.kind() != ast.ASTKind.Name: return 0 + nm: ast.Name* = ast.Name*(sb.value) + if nm.id is None: return 0 + if string.strcmp(nm.id, "OptionT") == 0: return 1 + if string.strcmp(nm.id, "NullableT") == 0: return 1 + if string.strcmp(nm.id, "OwnT") != 0: return 0 + node = sb.slice + depth += 1 return 0