diff --git a/compiler/ast.nim b/compiler/ast.nim index 556df74080b0..bc28cff845ca 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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 = "" 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.. 0: + setLen(dest.sonsImpl, 1) + dest.sonsImpl[0] = src.sonsImpl[0] + else: + newSons(dest, src.len) + for i in 0.. 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 diff --git a/compiler/seminst.nim b/compiler/seminst.nim index b34c7ef58eff..a34467636a3b 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -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) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 031683d04ab5..5b6620810591 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -542,14 +542,12 @@ proc eraseVoidParams*(t: PType) = for i in FirstParamAt..