feat(tpc): 禁止类型联合 T1 | T2 并优化错误提示

四类类型注解入口统一调用 RejectTypeUnion:任意 T1 | T2 直接报错,报文含行号与 CPtr[T]/rawptr[T]、const/volatile/static/export/extern 替代写法;仅保留内建修饰标记与类型的组合。
This commit is contained in:
TermiNexus committed 2026-10-18 13:08:24 +08:00
1 parent f19d25782f
commit 3269775945
5 files changed
+54 -4

No files matched your search

+3 -1
View File
@@ -10,7 +10,7 @@ import llvmlite.ir as ir
from lib.core import TypeSystem
from lib.core.TypeSystem import CTypeRegistry
from lib.core.SymbolUtils import (
IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode, IsCPtrNode,
IsListAnnotation, AnnotationContainsName, RejectTypeUnion, IsCPtrSubscriptNode, IsCPtrNode,
IsRawPtrSubscriptNode, IsPtrSubscriptNode, ResolveGenericTypeArgStr,
EnumClassIntWidth, ClassHasFuncLevelCVTable)
@@ -1187,6 +1187,8 @@ class DeclarationGenerator:
if annotation is None:
return 'i8*'
RejectTypeUnion(annotation)
non_struct_types: set[str] = {'list', 'dict', 'tuple', 'set', 'array', 'CArray', 'rawarray'}
if isinstance(annotation, ast.Name):
+2 -1
View File
@@ -5,7 +5,7 @@ if TYPE_CHECKING:
from typing import List
from lib.core.Handles.HandlesBase import BaseHandle, CTypeHelper, CTypeInfo
from lib.core.SymbolUtils import (
IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode,
IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode, RejectTypeUnion,
DesugarPtrSubscriptToUnion)
from lib.core import TypeSystem
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
@@ -27,6 +27,7 @@ class HandlesTypeMerge(BaseHandle):
def GetCTypeInfo(self, Node: ast.AST) -> CTypeInfo:
"""获取 CTypeInfo 对象"""
RejectTypeUnion(Node)
Result = self._GetCTypeInfoInternal(Node)
if isinstance(Result, CTypeInfo):
return Result
+2 -1
View File
@@ -19,7 +19,7 @@ if TYPE_CHECKING:
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap
from lib.core.SymbolUtils import (
IsListAnnotation, IsCPtrNode, IsCPtrSubscriptNode,
IsListAnnotation, RejectTypeUnion, IsCPtrNode, IsCPtrSubscriptNode,
IsRawPtrSubscriptNode, EnumIntWidth,
ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab)
from lib.core import TypeSystem as _t
@@ -121,6 +121,7 @@ class LLVMTypeMapper:
if node is None:
self._symtab.diagnostics.warn('', 0, "类型注解为 None,回退到 i32")
return 'i32'
RejectTypeUnion(node)
if isinstance(node, ast.Name):
return self._resolve_name(node)
elif isinstance(node, ast.Attribute):
+45
View File
@@ -2160,6 +2160,51 @@ def RequireNameDefined(Gen: object, Trans: object, Node: object, Name: str) -> N
)
# 类型注解中允许出现在 `|` 一侧的内建修饰标记。除此之外的任何 `T1 | T2`
# 都视为「类型联合」并直接拒绝:类型注解只能是单一类型。
_UNION_MARKER_NAMES: frozenset[str] = frozenset({
'CConst', 'CVolatile', 'CExport', 'CExtern', 'CStatic', 'CInline', 'State',
'CDefine', 'CTypedef', 'CPtr', 'CArrayPtr', 'CAutoPtr', 'CRef', 'CTempRef',
'BigEndian', 'LittleEndian', 'Bit',
})
def _IsUnionMarkerNode(node: ast.AST) -> bool:
"""节点是否为内建修饰标记(裸名、attr.* 或带调用括号的标记)。"""
if isinstance(node, ast.Name):
return node.id in _UNION_MARKER_NAMES
if isinstance(node, ast.Attribute):
cur: ast.AST = node
while isinstance(cur, ast.Attribute):
cur = cur.value
return isinstance(cur, ast.Name) and cur.id == 'attr'
if isinstance(node, ast.Call):
return _IsUnionMarkerNode(node.func)
return False
def _ContainsUnionMarker(node: ast.AST) -> bool:
if _IsUnionMarkerNode(node):
return True
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
return _ContainsUnionMarker(node.left) or _ContainsUnionMarker(node.right)
return False
def RejectTypeUnion(Annotation: ast.AST | None) -> None:
"""拒绝 `T1 | T2` 类型联合;只允许「单一类型 | 内建修饰标记」。"""
if not (isinstance(Annotation, ast.BinOp) and isinstance(Annotation.op, ast.BitOr)):
return
if _ContainsUnionMarker(Annotation):
return
Line: int = getattr(Annotation, 'lineno', 0) or 0
raise TypeError(
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行)。"
f"类型注解只能是单一类型:指针请写 CPtr[T] / rawptr[T];"
f"const / volatile / static / export / extern 请使用对应关键字。"
)
def AnnotationContainsMarker(node: ast.AST, MarkerName: str) -> bool:
"""注解 AST 中是否出现指定内建标记名(裸名,或属性形态的尾名)。"""
if isinstance(node, ast.Name):
+2 -1
View File
@@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
from lib.core.Handles.HandlesBase import CTypeInfo, BuiltinTypeMap, CTypeHelper
from lib.core.ConstEvaluator import ConstEvaluator
from lib.core.SymbolUtils import (
IsListAnnotation,
IsListAnnotation, RejectTypeUnion,
ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab)
from lib.core import TypeSystem
from lib.constants.config import mode as _config_mode
@@ -91,6 +91,7 @@ class TypeAnnotationResolver:
Node: AST 节点(如 ast.Name, ast.Attribute 等)
SymbolTable: 符号表字典
"""
RejectTypeUnion(Node)
if isinstance(Node, ast.Constant):
return TypeAnnotationResolver._from_node_constant(Node, SymbolTable)
if isinstance(Node, ast.Name):