Refactoring #25302; don't store procedure's parameter types to PType.sonsImpl (#25351)

This commit is contained in:
Tomohiro
2025-12-27 05:59:38 +09:00
committed by GitHub
parent a061f026a8
commit c48347136f
6 changed files with 69 additions and 31 deletions

View File

@@ -549,18 +549,28 @@ proc addAllowNil*(father, son: PNode) {.inline.} =
father.sons.add(son)
proc add*(father, son: PType) =
assert father.kind != tyProc or father.sonsImpl.len == 0
assert son != nil
father.sonsImpl.add son
proc addAllowNil*(father, son: PType) {.inline.} =
assert father.kind != tyProc or father.sonsImpl.len == 0
father.sonsImpl.add son
template `[]`*(n: PType, i: int): PType =
if n.state == Partial: loadType(n)
n.sonsImpl[i]
if n.kind == tyProc and i > 0:
assert n.nImpl[i] != nil and n.nImpl[i].sym != nil
n.nImpl[i].sym.typ
else:
n.sonsImpl[i]
template `[]=`*(n: PType, i: int; x: PType) =
if n.state == Partial: loadType(n)
n.sonsImpl[i] = x
if n.kind == tyProc and i > 0:
assert n.nImpl[i] != nil and n.nImpl[i].sym != nil
n.nImpl[i].sym.typ = x
else:
n.sonsImpl[i] = x
template `[]`*(n: PType, i: BackwardsIndex): PType =
if n.state == Partial: loadType(n)
@@ -806,7 +816,10 @@ proc replaceSon*(n: PNode; i: int; newson: PNode) {.inline.} =
proc last*(n: PType): PType {.inline.} =
if n.state == Partial: loadType(n)
n.sonsImpl[^1]
if n.kind == tyProc and n.nImpl.len > 1:
n.nImpl[^1].sym.typ
else:
n.sonsImpl[^1]
proc elementType*(n: PType): PType {.inline.} =
if n.state == Partial: loadType(n)
@@ -842,7 +855,10 @@ proc setIndexType*(n, idx: PType) {.inline.} =
proc firstParamType*(n: PType): PType {.inline.} =
if n.state == Partial: loadType(n)
n.sonsImpl[1]
if n.kind == tyProc:
n.nImpl[1].sym.typ
else:
n.sonsImpl[1]
proc firstGenericParam*(n: PType): PType {.inline.} =
if n.state == Partial: loadType(n)
@@ -914,10 +930,13 @@ proc `$`*(s: PSym): string =
result = "<nil>"
proc len*(n: PType): int {.inline.} =
result = n.sonsImpl.len
if n.kind == tyProc:
result = if n.nImpl == nil: 0 else: n.nImpl.len
else:
result = n.sonsImpl.len
proc sameTupleLengths*(a, b: PType): bool {.inline.} =
result = a.sonsImpl.len == b.sonsImpl.len
result = a.len == b.len
iterator tupleTypePairs*(a, b: PType): (int, PType, PType) =
for i in 0 ..< a.len:
@@ -1012,15 +1031,20 @@ proc newType*(kind: TTypeKind; idgen: IdGenerator; owner: PSym; son: sink PType
alignImpl: defaultAlignment, itemId: id,
uniqueId: id, sonsImpl: @[])
if son != nil:
assert kind != tyProc
result.sonsImpl.add son
when false:
if result.itemId.module == 55 and result.itemId.item == 2:
echo "KNID ", kind
writeStackTrace()
proc setSons*(dest: PType; sons: sink seq[PType]) {.inline.} = dest.sonsImpl = sons
proc setSon*(dest: PType; son: sink PType) {.inline.} = dest.sonsImpl = @[son]
proc setSons*(dest: PType; sons: sink seq[PType]) {.inline.} =
assert dest.kind != tyProc or sons.len <= 1
dest.sonsImpl = sons
proc setSon*(dest: PType; son: sink PType) {.inline.} =
dest.sonsImpl = @[son]
proc setSonsLen*(dest: PType; len: int) {.inline.} =
assert dest.kind != tyProc or len <= 1
setLen(dest.sonsImpl, len)
proc mergeLoc(a: var TLoc, b: TLoc) =
@@ -1034,6 +1058,7 @@ proc newSons*(father: PNode, length: int) =
setLen(father.sons, length)
proc newSons*(father: PType, length: int) =
assert father.kind != tyProc or length <= 1
setLen(father.sonsImpl, length)
proc truncateInferredTypeCandidates*(t: PType) {.inline.} =
@@ -1058,8 +1083,16 @@ proc assignType*(dest, src: PType) =
mergeLoc(dest.sym.locImpl, src.sym.loc)
else:
dest.symImpl = src.sym
newSons(dest, src.len)
for i in 0..<src.len: dest[i] = src[i]
if src.kind == tyProc:
# `tyProc` uses only `sonsImpl[0]` to store return type.
# parameter symbols and types are stored in `nImpl`.
assert src.sonsImpl.len <= 1
if src.len > 0:
setLen(dest.sonsImpl, 1)
dest.sonsImpl[0] = src.sonsImpl[0]
else:
newSons(dest, src.len)
for i in 0..<src.len: dest[i] = src[i]
proc copyType*(t: PType, idgen: IdGenerator, owner: PSym): PType =
result = newType(t.kind, idgen, owner)
@@ -1169,7 +1202,8 @@ proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) =
proc rawAddSon*(father, son: PType; propagateHasAsgn = true) =
ensureMutable father
father.sonsImpl.add(son)
if father.kind != tyProc or father.sonsImpl.len == 0:
father.sonsImpl.add(son)
if not son.isNil: propagateToOwner(father, son, propagateHasAsgn)
proc addSonNilAllowed*(father, son: PNode) =
@@ -1575,7 +1609,7 @@ proc newProcType*(info: TLineInfo; idgen: IdGenerator; owner: PSym): PType =
result.n.add newNodeI(nkEffectList, info)
proc addParam*(procType: PType; param: PSym) =
param.position = procType.sons.len-1
param.position = procType.n.len - 1
procType.n.add newSymNode(param)
rawAddSon(procType, param.typ)

View File

@@ -370,8 +370,14 @@ proc storeType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemI
paddingAtEnd: t.paddingAtEnd)
storeNode(p, t, n)
p.typeInst = t.typeInst.storeType(c, m)
for kid in kids t:
p.types.add kid.storeType(c, m)
if t.kind == tyProc and t.len > 0:
# if kind == tyProc, parameter types are stored in t.n
# and you can access them with `kits` iterator.
# return type is stored in t.sons[0].
p.types.add t[0].storeType(c, m)
else:
for kid in kids t:
p.types.add kid.storeType(c, m)
c.addMissing t.sym
p.sym = t.sym.safeItemId(c, m)
c.addMissing t.owner

View File

@@ -244,7 +244,8 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
var result = instCopyType(cl, prc.typ)
let originalParams = result.n
result.n = originalParams.shallowCopy
for i, resulti in paramTypes(result):
for i in 1 ..< originalParams.len:
let resulti = originalParams[i].sym.typ
# twrong_field_caching requires these 'resetIdTable' calls:
if i > FirstParamAt:
resetIdTable(cl.symMap)
@@ -258,23 +259,23 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
let needsTypeDescSkipping = resulti.kind == tyTypeDesc and tfUnresolved in resulti.flags
if resulti.kind == tyFromExpr:
resulti.incl tfNonConstExpr
result[i] = replaceTypeVarsT(cl, resulti)
var paramType = replaceTypeVarsT(cl, resulti)
if needsStaticSkipping:
result[i] = result[i].skipTypes({tyStatic})
paramType = paramType.skipTypes({tyStatic})
if needsTypeDescSkipping:
result[i] = result[i].skipTypes({tyTypeDesc})
typeToFit = result[i]
paramType = paramType.skipTypes({tyTypeDesc})
typeToFit = paramType
# ...otherwise, we use the instantiated type in `fitNode`
if (typeToFit.kind != tyTypeDesc or typeToFit.base.kind != tyNone) and
(typeToFit.kind != tyStatic):
typeToFit = result[i]
typeToFit = paramType
internalAssert c.config, originalParams[i].kind == nkSym
let oldParam = originalParams[i].sym
let param = copySym(oldParam, c.idgen)
setOwner(param, prc)
param.typ = result[i]
param.typ = paramType
# The default value is instantiated and fitted against the final
# concrete param type. We avoid calling `replaceTypeVarsN` on the
@@ -305,12 +306,12 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
param.ast.typ = def.typ
else:
param.ast = fitNodePostMatch(c, typeToFit, converted)
param.typ = result[i]
param.typ = paramType
result.n[i] = newSymNode(param)
if isRecursiveStructuralType(result[i]):
if isRecursiveStructuralType(paramType):
localError(c.config, originalParams[i].sym.info, "illegal recursion in type '" & typeToString(result[i]) & "'")
propagateToOwner(result, result[i])
propagateToOwner(result, paramType)
addDecl(c, param)
resetIdTable(cl.symMap)

View File

@@ -553,14 +553,12 @@ proc eraseVoidParams*(t: PType) =
for i in FirstParamAt..<t.signatureLen:
# don't touch any memory unless necessary
if t[i].kind == tyVoid:
if t.n[i].kind == nkRecList or t[i].kind == tyVoid:
var pos = i
for j in i+1..<t.signatureLen:
if t[j].kind != tyVoid:
t[pos] = t[j]
t.n[pos] = t.n[j]
inc pos
newSons t, pos
setLen t.n.sons, pos
break
@@ -754,7 +752,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType, isInstValue = false):
let r2 = r.skipTypes({tyAlias, tySink, tyOwned})
if r2.kind in {tyPtr, tyRef}:
r = skipTypes(r2, {tyPtr, tyRef})
result[i] = r
if result.kind != tyProc or i == 0:
result[i] = r
if result.kind != tyArray or i != 0:
propagateToOwner(result, r)
# bug #4677: Do not instantiate effect lists

View File

@@ -233,13 +233,11 @@ proc copyingEraseVoidParams(m: TCandidate, t: var PType) =
if not copied:
# keep first i children
t = copyType(original, m.c.idgen, t.owner)
t.setSonsLen(i)
t.n = copyNode(original.n)
t.n.sons = original.n.sons
t.n.sons.setLen(i)
copied = true
elif copied:
t.add(f)
t.n.add(original.n[i])
proc initCandidate*(ctx: PContext, callee: PSym,

View File

@@ -38,7 +38,7 @@ proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNod
sinkType.add argType
arg.sym.typ = sinkType
owner.typ[arg.sym.position+1] = sinkType
assert owner.typ.n[arg.sym.position+1].sym == arg.sym
#message(config, arg.info, warnUser,
# ("turned '$1' to a sink parameter") % [$arg])