diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2023-12-14 16:25:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-14 16:25:34 +0100 |
commit | 6ed33b6d61518c8de94b07c7ffb68fcc6f839897 (patch) | |
tree | 037796db0c0cb1efee88ec582442b719b422699d | |
parent | 1b7b0d69db41b3c5a27cca643d66c0acabbe41df (diff) | |
download | Nim-6ed33b6d61518c8de94b07c7ffb68fcc6f839897.tar.gz |
type graph refactor; part 3 (#23064)
-rw-r--r-- | compiler/ast.nim | 82 | ||||
-rw-r--r-- | compiler/astalgo.nim | 69 | ||||
-rw-r--r-- | compiler/docgen.nim | 3 | ||||
-rw-r--r-- | compiler/expanddefaults.nim | 2 | ||||
-rw-r--r-- | compiler/ic/ic.nim | 2 | ||||
-rw-r--r-- | compiler/isolation_check.nim | 16 | ||||
-rw-r--r-- | compiler/semdata.nim | 2 | ||||
-rw-r--r-- | compiler/sempass2.nim | 2 | ||||
-rw-r--r-- | compiler/semstmts.nim | 12 | ||||
-rw-r--r-- | compiler/semtypes.nim | 2 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 30 | ||||
-rw-r--r-- | compiler/sizealignoffsetimpl.nim | 11 | ||||
-rw-r--r-- | compiler/typeallowed.nim | 27 | ||||
-rw-r--r-- | compiler/types.nim | 246 | ||||
-rw-r--r-- | compiler/varpartitions.nim | 3 | ||||
-rw-r--r-- | compiler/vmdeps.nim | 2 | ||||
-rw-r--r-- | tests/typerel/tregionptrs.nim | 16 |
17 files changed, 257 insertions, 270 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index ab46a02d6..c880cb651 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1199,9 +1199,6 @@ proc discardSons*(father: PNode) proc len*(n: PNode): int {.inline.} = result = n.sons.len -proc len*(n: PType): int {.inline.} = - result = n.sons.len - proc safeLen*(n: PNode): int {.inline.} = ## works even for leaves. if n.kind in {nkNone..nkNilLit}: result = 0 @@ -1576,11 +1573,74 @@ proc `$`*(s: PSym): string = else: result = "<nil>" -iterator items*(t: PType): PType = +when false: + iterator items*(t: PType): PType = + for i in 0..<t.sons.len: yield t.sons[i] + + iterator pairs*(n: PType): tuple[i: int, n: PType] = + for i in 0..<n.sons.len: yield (i, n.sons[i]) + +when true: + proc len*(n: PType): int {.inline.} = + result = n.sons.len + +proc sameTupleLengths*(a, b: PType): bool {.inline.} = + result = a.sons.len == b.sons.len + +iterator tupleTypePairs*(a, b: PType): (int, PType, PType) = + for i in 0 ..< a.sons.len: + yield (i, a.sons[i], b.sons[i]) + +iterator underspecifiedPairs*(a, b: PType; start = 0; without = 0): (PType, PType) = + # XXX Figure out with what typekinds this is called. + for i in start ..< a.sons.len + without: + yield (a.sons[i], b.sons[i]) + +proc signatureLen*(t: PType): int {.inline.} = + result = t.sons.len + +proc kidsLen*(t: PType): int {.inline.} = + result = t.sons.len + +proc genericParamHasConstraints*(t: PType): bool {.inline.} = t.sons.len > 0 + +proc hasElementType*(t: PType): bool {.inline.} = t.sons.len > 0 +proc isEmptyTupleType*(t: PType): bool {.inline.} = t.sons.len == 0 +proc isSingletonTupleType*(t: PType): bool {.inline.} = t.sons.len == 1 + +iterator genericInstParams*(t: PType): (bool, PType) = + for i in 1..<t.sons.len-1: + yield (i!=1, t.sons[i]) + +iterator genericInvocationParams*(t: PType): (bool, PType) = + for i in 1..<t.sons.len: + yield (i!=1, t.sons[i]) + +iterator genericBodyParams*(t: PType): (bool, PType) = + for i in 0..<t.sons.len-1: + yield (i!=0, t.sons[i]) + +iterator userTypeClassInstParams*(t: PType): (bool, PType) = + for i in 1..<t.sons.len-1: + yield (i!=1, t.sons[i]) + +iterator ikids*(t: PType): (int, PType) = + for i in 0..<t.sons.len: yield (i, t.sons[i]) + +const + FirstParamAt* = 1 + +iterator paramTypes*(t: PType): (int, PType) = + for i in FirstParamAt..<t.sons.len: yield (i, t.sons[i]) + +template paramTypeToNodeIndex*(x: int): int = x + +iterator kids*(t: PType): PType = for i in 0..<t.sons.len: yield t.sons[i] -iterator pairs*(n: PType): tuple[i: int, n: PType] = - for i in 0..<n.sons.len: yield (i, n.sons[i]) +iterator signature*(t: PType): PType = + # yields return type + parameter types + for i in 0..<t.sons.len: yield t.sons[i] proc newType*(kind: TTypeKind; idgen: IdGenerator; owner: PSym; son: sink PType = nil): PType = let id = nextTypeId idgen @@ -1624,8 +1684,8 @@ proc assignType*(dest, src: PType) = mergeLoc(dest.sym.loc, src.sym.loc) else: dest.sym = src.sym - newSons(dest, src.len) - for i in 0..<src.len: dest[i] = src[i] + newSons(dest, src.sons.len) + for i in 0..<src.sons.len: dest[i] = src[i] proc copyType*(t: PType, idgen: IdGenerator, owner: PSym): PType = result = newType(t.kind, idgen, owner) @@ -1705,7 +1765,7 @@ proc skipTypesOrNil*(t: PType, kinds: TTypeKinds): PType = ## same as skipTypes but handles 'nil' result = t while result != nil and result.kind in kinds: - if result.len == 0: return nil + if result.sons.len == 0: return nil result = last(result) proc isGCedMem*(t: PType): bool {.inline.} = @@ -2084,7 +2144,7 @@ proc findUnresolvedStatic*(n: PNode): PNode = return n if n.typ != nil and n.typ.kind == tyTypeDesc: let t = skipTypes(n.typ, {tyTypeDesc}) - if t.kind == tyGenericParam and t.len == 0: + if t.kind == tyGenericParam and not t.genericParamHasConstraints: return n for son in n: let n = son.findUnresolvedStatic @@ -2145,7 +2205,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.len-1 + param.position = procType.sons.len-1 procType.n.add newSymNode(param) rawAddSon(procType, param.typ) diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 9b3a42ebe..238aa6776 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -37,15 +37,6 @@ proc debug*(n: PSym; conf: ConfigRef = nil) {.exportc: "debugSym", deprecated.} proc debug*(n: PType; conf: ConfigRef = nil) {.exportc: "debugType", deprecated.} proc debug*(n: PNode; conf: ConfigRef = nil) {.exportc: "debugNode", deprecated.} -proc typekinds*(t: PType) {.deprecated.} = - var t = t - var s = "" - while t != nil and t.len > 0: - s.add $t.kind - s.add " " - t = t.last - echo s - template debug*(x: PSym|PType|PNode) {.deprecated.} = when compiles(c.config): debug(c.config, x) @@ -337,21 +328,18 @@ proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int, sonsRope = "\"$1 @$2\"" % [rope($n.kind), rope( strutils.toHex(cast[int](n), sizeof(n) * 2))] else: - if n.len > 0: - sonsRope = rope("[") - for i in 0..<n.len: - if i > 0: sonsRope.add(",") - sonsRope.addf("$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, n[i], - marker, indent + 4, maxRecDepth - 1)]) - sonsRope.addf("$N$1]", [rspaces(indent + 2)]) - else: - sonsRope = rope("null") + sonsRope = rope("[") + for i, a in n.ikids: + if i > 0: sonsRope.add(",") + sonsRope.addf("$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, a, + marker, indent + 4, maxRecDepth - 1)]) + sonsRope.addf("$N$1]", [rspaces(indent + 2)]) let istr = rspaces(indent + 2) result = rope("{") result.addf("$N$1\"kind\": $2", [istr, makeYamlString($n.kind)]) result.addf("$N$1\"sym\": $2", [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth - 1)]) - result.addf("$N$1\"n\": $2", [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)]) + result.addf("$N$1\"n\": $2", [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)]) if card(n.flags) > 0: result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)]) result.addf("$N$1\"callconv\": $2", [istr, makeYamlString($n.callConv)]) @@ -573,14 +561,12 @@ proc value(this: var DebugPrinter; value: PType) = this.key "n" this.value value.n - if value.len > 0: - this.key "sons" - this.openBracket - for i in 0..<value.len: - this.value value[i] - if i != value.len - 1: - this.comma - this.closeBracket + this.key "sons" + this.openBracket + for i, a in value.ikids: + if i > 0: this.comma + this.value a + this.closeBracket if value.n != nil: this.key "n" @@ -649,30 +635,33 @@ proc value(this: var DebugPrinter; value: PNode) = proc debug(n: PSym; conf: ConfigRef) = - var this: DebugPrinter - this.visited = initTable[pointer, int]() - this.renderSymType = true - this.useColor = not defined(windows) + var this = DebugPrinter( + visited: initTable[pointer, int](), + renderSymType: true, + useColor: not defined(windows) + ) this.value(n) echo($this.res) proc debug(n: PType; conf: ConfigRef) = - var this: DebugPrinter - this.visited = initTable[pointer, int]() - this.renderSymType = true - this.useColor = not defined(windows) + var this = DebugPrinter( + visited: initTable[pointer, int](), + renderSymType: true, + useColor: not defined(windows) + ) this.value(n) echo($this.res) proc debug(n: PNode; conf: ConfigRef) = - var this: DebugPrinter - this.visited = initTable[pointer, int]() - #this.renderSymType = true - this.useColor = not defined(windows) + var this = DebugPrinter( + visited: initTable[pointer, int](), + renderSymType: false, + useColor: not defined(windows) + ) this.value(n) echo($this.res) -proc nextTry(h, maxHash: Hash): Hash = +proc nextTry(h, maxHash: Hash): Hash {.inline.} = result = ((5 * h) + 1) and maxHash # For any initial h in range(maxHash), repeating that maxHash times # generates each int in range(maxHash) exactly once (see any text on diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 29eeced9b..b53307ee0 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -1199,8 +1199,7 @@ proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind, nonExports = false): var param = %{"name": %($genericParam)} if genericParam.sym.typ.len > 0: param["types"] = newJArray() - for kind in genericParam.sym.typ: - param["types"].add %($kind) + param["types"].add %($genericParam.sym.typ.elementType) result.json["signature"]["genericParams"].add param if optGenIndex in d.conf.globalOptions: genItem(d, n, nameNode, k, kForceExport) diff --git a/compiler/expanddefaults.nim b/compiler/expanddefaults.nim index 395d31cc8..86f87cd84 100644 --- a/compiler/expanddefaults.nim +++ b/compiler/expanddefaults.nim @@ -118,7 +118,7 @@ proc expandDefault(t: PType; info: TLineInfo): PNode = expandDefaultObj(t, info, result) of tyTuple: result = newZero(t, info, nkTupleConstr) - for it in t: + for it in t.kids: result.add expandDefault(it, info) of tyVarargs, tyOpenArray, tySequence, tyUncheckedArray: result = newZero(t, info, nkBracket) diff --git a/compiler/ic/ic.nim b/compiler/ic/ic.nim index 0085ea748..a7d3ed81c 100644 --- a/compiler/ic/ic.nim +++ b/compiler/ic/ic.nim @@ -370,7 +370,7 @@ 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 items t: + for kid in kids t: p.types.add kid.storeType(c, m) c.addMissing t.sym p.sym = t.sym.safeItemId(c, m) diff --git a/compiler/isolation_check.nim b/compiler/isolation_check.nim index 08a2cc604..17fbde29e 100644 --- a/compiler/isolation_check.nim +++ b/compiler/isolation_check.nim @@ -54,14 +54,14 @@ proc canAlias(arg, ret: PType; marker: var IntSet): bool = of tyObject: if isFinal(ret): result = canAliasN(arg, ret.n, marker) - if not result and ret.len > 0 and ret[0] != nil: - result = canAlias(arg, ret[0], marker) + if not result and ret.baseClass != nil: + result = canAlias(arg, ret.baseClass, marker) else: result = true of tyTuple: result = false - for i in 0..<ret.len: - result = canAlias(arg, ret[i], marker) + for r in ret.kids: + result = canAlias(arg, r, marker) if result: break of tyArray, tySequence, tyDistinct, tyGenericInst, tyAlias, tyInferred, tySink, tyLent, tyOwned, tyRef: @@ -124,9 +124,11 @@ proc containsDangerousRefAux(t: PType; marker: var IntSet): SearchResult = if result == NotFound: result = containsDangerousRefAux(t.n, marker) of tyGenericInst, tyDistinct, tyAlias, tySink: result = containsDangerousRefAux(skipModifier(t), marker) - of tyArray, tySet, tyTuple, tySequence: - for i in 0..<t.len: - result = containsDangerousRefAux(t[i], marker) + of tyArray, tySet, tySequence: + result = containsDangerousRefAux(t.elementType, marker) + of tyTuple: + for a in t.kids: + result = containsDangerousRefAux(a, marker) if result == Found: return result else: discard diff --git a/compiler/semdata.nim b/compiler/semdata.nim index c066e3a7b..f3d661ff1 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -468,7 +468,7 @@ proc makeOrType*(c: PContext, t1, t2: PType): PType = result = newTypeS(tyOr, c) template addOr(t1) = if t1.kind == tyOr: - for x in t1: result.rawAddSon x + for x in t1.kids: result.rawAddSon x else: result.rawAddSon t1 addOr(t1) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 8fc218955..36611fd27 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -1421,7 +1421,7 @@ proc track(tracked: PEffects, n: PNode) = proc subtypeRelation(g: ModuleGraph; spec, real: PNode): bool = if spec.typ.kind == tyOr: result = false - for t in spec.typ: + for t in spec.typ.kids: if safeInheritanceDiff(g.excType(real), t) <= 0: return true else: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 22e863c5c..eacda7f9b 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -45,7 +45,7 @@ proc hasEmpty(typ: PType): bool = result = typ.elementType.kind == tyEmpty elif typ.kind == tyTuple: result = false - for s in typ: + for s in typ.kids: result = result or hasEmpty(s) else: result = false @@ -1362,7 +1362,7 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) = of tyArray: return traverseSubTypes(c, t.elementType) of tyProc: - for subType in t: + for subType in t.signature: if subType != nil: subresult traverseSubTypes(c, subType) if result: @@ -1395,11 +1395,11 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) = of tyUserTypeClass, tyUserTypeClassInst: error("non-invariant type parameters are not supported in concepts") of tyTuple: - for fieldType in t: + for fieldType in t.kids: subresult traverseSubTypes(c, fieldType) of tyPtr, tyRef, tyVar, tyLent: - if t.base.kind == tyGenericParam: return true - return traverseSubTypes(c, t.base) + if t.elementType.kind == tyGenericParam: return true + return traverseSubTypes(c, t.elementType) of tyDistinct, tyAlias, tySink, tyOwned: return traverseSubTypes(c, t.skipModifier) of tyGenericInst: @@ -2086,7 +2086,7 @@ proc semCppMember(c: PContext; s: PSym; n: PNode) = if c.config.backend == backendCpp: if s.typ.len < 2 and not isCtor: localError(c.config, n.info, pragmaName & " must have at least one parameter") - for son in s.typ: + for son in s.typ.signature: if son!=nil and son.isMetaType: localError(c.config, n.info, pragmaName & " unsupported for generic routine") var typ: PType diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 337714142..fe87c2973 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1036,7 +1036,7 @@ proc findEnforcedStaticType(t: PType): PType = if t == nil: return nil if t.kind == tyStatic: return t if t.kind == tyAnd: - for s in t: + for s in t.kids: let t = findEnforcedStaticType(s) if t != nil: return t diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 38cc66637..9d26b71a3 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -227,7 +227,7 @@ proc sumGeneric(t: PType): int = inc result of tyOr: var maxBranch = 0 - for branch in t: + for branch in t.kids: let branchSum = sumGeneric(branch) if branchSum > maxBranch: maxBranch = branchSum inc result, maxBranch @@ -240,11 +240,16 @@ proc sumGeneric(t: PType): int = t = t.elementType if t.kind == tyEmpty: break inc result - of tyGenericInvocation, tyTuple, tyProc, tyAnd: + of tyGenericInvocation, tyTuple, tyAnd: result += ord(t.kind in {tyGenericInvocation, tyAnd}) - for i in 0..<t.len: - if t[i] != nil: - result += sumGeneric(t[i]) + for a in t.kids: + if a != nil: + result += sumGeneric(a) + break + of tyProc: + result += sumGeneric(t.returnType) + for _, a in t.paramTypes: + result += sumGeneric(a) break of tyStatic: return sumGeneric(t.skipModifier) + 1 @@ -1146,7 +1151,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, # both int and string must match against number # but ensure that '[T: A|A]' matches as good as '[T: A]' (bug #2219): result = isGeneric - for branch in a: + for branch in a.kids: let x = typeRel(c, f, branch, flags + {trDontBind}) if x == isNone: return isNone if x < result: result = x @@ -1156,7 +1161,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, c.typedescMatched = true # seq[Sortable and Iterable] vs seq[Sortable] # only one match is enough - for branch in a: + for branch in a.kids: let x = typeRel(c, f, branch, flags + {trDontBind}) if x != isNone: return if x >= isGeneric: isGeneric else: x @@ -1660,7 +1665,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, of tyAnd: considerPreviousT: result = isEqual - for branch in f: + for branch in f.kids: let x = typeRel(c, branch, aOrig, flags) if x < isSubtype: return isNone # 'and' implies minimum matching result: @@ -1672,7 +1677,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, result = isNone let oldInheritancePenalty = c.inheritancePenalty var maxInheritance = 0 - for branch in f: + for branch in f.kids: c.inheritancePenalty = 0 let x = typeRel(c, branch, aOrig, flags) maxInheritance = max(maxInheritance, c.inheritancePenalty) @@ -1686,9 +1691,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, c.inheritancePenalty = oldInheritancePenalty + maxInheritance of tyNot: considerPreviousT: - for branch in f: - if typeRel(c, branch, aOrig, flags) != isNone: - return isNone + if typeRel(c, f.elementType, aOrig, flags) != isNone: + return isNone bindingRet isGeneric of tyAnything: @@ -1699,7 +1703,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, return isGeneric of tyBuiltInTypeClass: considerPreviousT: - let target = f[0] + let target = f.genericHead let targetKind = target.kind var effectiveArgType = a.getObjectTypeOrNil() if effectiveArgType == nil: return isNone diff --git a/compiler/sizealignoffsetimpl.nim b/compiler/sizealignoffsetimpl.nim index 7cc11f55f..d114f59da 100644 --- a/compiler/sizealignoffsetimpl.nim +++ b/compiler/sizealignoffsetimpl.nim @@ -332,8 +332,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) = of tyTuple: try: var accum = OffsetAccum(maxAlign: 1) - for i in 0..<typ.len: - let child = typ[i] + for i, child in typ.ikids: computeSizeAlign(conf, child) accum.align(child.align) if typ.n != nil: # is named tuple (has field symbols)? @@ -403,16 +402,16 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) = typ.align = szIllegalRecursion typ.paddingAtEnd = szIllegalRecursion of tyInferred: - if typ.len > 0: + if typ.hasElementType: computeSizeAlign(conf, typ.last) typ.size = typ.last.size typ.align = typ.last.align typ.paddingAtEnd = typ.last.paddingAtEnd of tyGenericInst, tyDistinct, tyGenericBody, tyAlias, tySink, tyOwned: - computeSizeAlign(conf, typ.last) - typ.size = typ.last.size - typ.align = typ.last.align + computeSizeAlign(conf, typ.skipModifier) + typ.size = typ.skipModifier.size + typ.align = typ.skipModifier.align typ.paddingAtEnd = typ.last.paddingAtEnd of tyTypeClasses: diff --git a/compiler/typeallowed.nim b/compiler/typeallowed.nim index 04dbc69c5..d226b2e06 100644 --- a/compiler/typeallowed.nim +++ b/compiler/typeallowed.nim @@ -96,9 +96,9 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, # only closure iterators may be assigned to anything. result = t let f = if kind in {skProc, skFunc}: flags+{taNoUntyped} else: flags - for i in 1..<t.len: + for _, a in t.paramTypes: if result != nil: break - result = typeAllowedAux(marker, t[i], skParam, c, f-{taIsOpenArray}) + result = typeAllowedAux(marker, a, skParam, c, f-{taIsOpenArray}) if result.isNil and t.returnType != nil: result = typeAllowedAux(marker, t.returnType, skResult, c, flags) of tyTypeDesc: @@ -179,17 +179,22 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, result = typeAllowedAux(marker, t.elementType, kind, c, flags+{taHeap}) of tySet: result = typeAllowedAux(marker, t.elementType, kind, c, flags) - of tyObject, tyTuple: + of tyObject: if kind in {skProc, skFunc, skConst} and - t.kind == tyObject and t.baseClass != nil and taIsDefaultField notin flags: + t.baseClass != nil and taIsDefaultField notin flags: result = t else: let flags = flags+{taField} - for i in 0..<t.len: - result = typeAllowedAux(marker, t[i], kind, c, flags) - if result != nil: break + result = typeAllowedAux(marker, t.baseClass, kind, c, flags) if result.isNil and t.n != nil: result = typeAllowedNode(marker, t.n, kind, c, flags) + of tyTuple: + let flags = flags+{taField} + for a in t.kids: + result = typeAllowedAux(marker, a, kind, c, flags) + if result != nil: break + if result.isNil and t.n != nil: + result = typeAllowedNode(marker, t.n, kind, c, flags) of tyEmpty: if kind in {skVar, skLet}: result = t of tyProxy: @@ -197,7 +202,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, # prevent cascading errors: result = nil of tyOwned: - if t.len == 1 and t.skipModifier.skipTypes(abstractInst).kind in {tyRef, tyPtr, tyProc}: + if t.hasElementType and t.skipModifier.skipTypes(abstractInst).kind in {tyRef, tyPtr, tyProc}: result = typeAllowedAux(marker, t.skipModifier, kind, c, flags+{taHeap}) else: result = t @@ -247,14 +252,14 @@ proc classifyViewTypeAux(marker: var IntSet, t: PType): ViewTypeKind = tyUncheckedArray, tySequence, tyArray, tyRef, tyStatic: result = classifyViewTypeAux(marker, skipModifier(t)) of tyFromExpr: - if t.len > 0: + if t.hasElementType: result = classifyViewTypeAux(marker, skipModifier(t)) else: result = noView of tyTuple: result = noView - for i in 0..<t.len: - result.combine classifyViewTypeAux(marker, t[i]) + for a in t.kids: + result.combine classifyViewTypeAux(marker, a) if result == mutableView: break of tyObject: result = noView diff --git a/compiler/types.nim b/compiler/types.nim index eef85f36a..7d7d3349d 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -68,13 +68,10 @@ template `$`*(typ: PType): string = typeToString(typ) # ------------------- type iterator: ---------------------------------------- type TTypeIter* = proc (t: PType, closure: RootRef): bool {.nimcall.} # true if iteration should stop - TTypeMutator* = proc (t: PType, closure: RootRef): PType {.nimcall.} # copy t and mutate it TTypePredicate* = proc (t: PType): bool {.nimcall.} proc iterOverType*(t: PType, iter: TTypeIter, closure: RootRef): bool # Returns result of `iter`. -proc mutateType*(t: PType, iter: TTypeMutator, closure: RootRef): PType - # Returns result of `iter`. type TParamsEquality* = enum # they are equal, but their @@ -228,8 +225,8 @@ proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter, of tyGenericInst, tyGenericBody, tyAlias, tySink, tyInferred: result = iterOverTypeAux(marker, skipModifier(t), iter, closure) else: - for i in 0..<t.len: - result = iterOverTypeAux(marker, t[i], iter, closure) + for a in t.kids: + result = iterOverTypeAux(marker, a, iter, closure) if result: return if t.n != nil and t.kind != tyProc: result = iterOverNode(marker, t.n, iter, closure) @@ -278,8 +275,8 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate, of tyGenericInst, tyDistinct, tyAlias, tySink: result = searchTypeForAux(skipModifier(t), predicate, marker) of tyArray, tySet, tyTuple: - for i in 0..<t.len: - result = searchTypeForAux(t[i], predicate, marker) + for a in t.kids: + result = searchTypeForAux(a, predicate, marker) if result: return else: discard @@ -307,7 +304,6 @@ type proc analyseObjectWithTypeFieldAux(t: PType, marker: var IntSet): TTypeFieldResult = - var res: TTypeFieldResult result = frNone if t == nil: return case t.kind @@ -315,20 +311,19 @@ proc analyseObjectWithTypeFieldAux(t: PType, if t.n != nil: if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker): return frEmbedded - for i in 0..<t.len: - var x = t[i] - if x != nil: x = x.skipTypes(skipPtrs) - res = analyseObjectWithTypeFieldAux(x, marker) - if res == frEmbedded: - return frEmbedded - if res == frHeader: result = frHeader + var x = t.baseClass + if x != nil: x = x.skipTypes(skipPtrs) + let res = analyseObjectWithTypeFieldAux(x, marker) + if res == frEmbedded: + return frEmbedded + if res == frHeader: result = frHeader if result == frNone: if isObjectWithTypeFieldPredicate(t): result = frHeader of tyGenericInst, tyDistinct, tyAlias, tySink: result = analyseObjectWithTypeFieldAux(skipModifier(t), marker) of tyArray, tyTuple: - for i in 0..<t.len: - res = analyseObjectWithTypeFieldAux(t[i], marker) + for a in t.kids: + let res = analyseObjectWithTypeFieldAux(a, marker) if res != frNone: return frEmbedded else: @@ -405,9 +400,7 @@ proc canFormAcycleAux(g: ModuleGraph, marker: var IntSet, typ: PType, orig: PTyp if withRef and sameBackendType(t, orig): result = true elif not containsOrIncl(marker, t.id): - for i in 0..<t.len: - result = canFormAcycleAux(g, marker, t[i], orig, withRef or t.kind != tyUncheckedArray, hasTrace) - if result: return + result = canFormAcycleAux(g, marker, t.elementType, orig, withRef or t.kind != tyUncheckedArray, hasTrace) of tyObject: if withRef and sameBackendType(t, orig): result = true @@ -416,8 +409,8 @@ proc canFormAcycleAux(g: ModuleGraph, marker: var IntSet, typ: PType, orig: PTyp let op = getAttachedOp(g, t.skipTypes({tyRef}), attachedTrace) if op != nil and sfOverridden in op.flags: hasTrace = true - for i in 0..<t.len: - result = canFormAcycleAux(g, marker, t[i], orig, withRef, hasTrace) + if t.baseClass != nil: + result = canFormAcycleAux(g, marker, t.baseClass, orig, withRef, hasTrace) if result: return if t.n != nil: result = canFormAcycleNode(g, marker, t.n, orig, withRef, hasTrace) # Inheritance can introduce cyclic types, however this is not relevant @@ -426,13 +419,18 @@ proc canFormAcycleAux(g: ModuleGraph, marker: var IntSet, typ: PType, orig: PTyp if tfFinal notin t.flags: # damn inheritance may introduce cycles: result = true - of tyTuple, tySequence, tyArray, tyOpenArray, tyVarargs: + of tyTuple: if withRef and sameBackendType(t, orig): result = true elif not containsOrIncl(marker, t.id): - for i in 0..<t.len: - result = canFormAcycleAux(g, marker, t[i], orig, withRef, hasTrace) + for a in t.kids: + result = canFormAcycleAux(g, marker, a, orig, withRef, hasTrace) if result: return + of tySequence, tyArray, tyOpenArray, tyVarargs: + if withRef and sameBackendType(t, orig): + result = true + elif not containsOrIncl(marker, t.id): + result = canFormAcycleAux(g, marker, t.elementType, orig, withRef, hasTrace) of tyProc: result = typ.callConv == ccClosure else: discard @@ -445,37 +443,6 @@ proc canFormAcycle*(g: ModuleGraph, typ: PType): bool = let t = skipTypes(typ, abstractInst+{tyOwned}-{tyTypeDesc}) result = canFormAcycleAux(g, marker, t, t, false, false) -proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator, - closure: RootRef): PType -proc mutateNode(marker: var IntSet, n: PNode, iter: TTypeMutator, - closure: RootRef): PNode = - result = nil - if n != nil: - result = copyNode(n) - result.typ = mutateTypeAux(marker, n.typ, iter, closure) - case n.kind - of nkNone..nkNilLit: - # a leaf - discard - else: - for i in 0..<n.len: - result.add mutateNode(marker, n[i], iter, closure) - -proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator, - closure: RootRef): PType = - result = nil - if t == nil: return - result = iter(t, closure) - if not containsOrIncl(marker, t.id): - for i in 0..<t.len: - result[i] = mutateTypeAux(marker, result[i], iter, closure) - if t.n != nil: result.n = mutateNode(marker, t.n, iter, closure) - assert(result != nil) - -proc mutateType(t: PType, iter: TTypeMutator, closure: RootRef): PType = - var marker = initIntSet() - result = mutateTypeAux(marker, t, iter, closure) - proc valueToString(a: PNode): string = case a.kind of nkCharLit, nkUIntLit..nkUInt64Lit: @@ -566,13 +533,9 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = elif prefer in {preferName, preferTypeName, preferInlayHint} or t.sym.owner.isNil: # note: should probably be: {preferName, preferTypeName, preferGenericArg} result = t.sym.name.s - if t.kind == tyGenericParam and t.len > 0: + if t.kind == tyGenericParam and t.genericParamHasConstraints: result.add ": " - var first = true - for son in t: - if not first: result.add " or " - result.add son.typeToString - first = false + result.add t.elementType.typeToString else: result = t.sym.owner.name.s & '.' & t.sym.name.s result.addTypeFlags(t) @@ -589,17 +552,23 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = result = "int" else: result = "int literal(" & $t.n.intVal & ")" - of tyGenericInst, tyGenericInvocation: + of tyGenericInst: result = typeToString(t.genericHead) & '[' - for i in 1..<t.len-ord(t.kind != tyGenericInvocation): - if i > 1: result.add(", ") - result.add(typeToString(t[i], preferGenericArg)) + for needsComma, a in t.genericInstParams: + if needsComma: result.add(", ") + result.add(typeToString(a, preferGenericArg)) + result.add(']') + of tyGenericInvocation: + result = typeToString(t.genericHead) & '[' + for needsComma, a in t.genericInvocationParams: + if needsComma: result.add(", ") + result.add(typeToString(a, preferGenericArg)) result.add(']') of tyGenericBody: result = typeToString(t.typeBodyImpl) & '[' - for i in 0..<t.len-1: - if i > 0: result.add(", ") - result.add(typeToString(t[i], preferTypeName)) + for needsComma, a in t.genericBodyParams: + if needsComma: result.add(", ") + result.add(typeToString(a, preferTypeName)) result.add(']') of tyTypeDesc: if t.elementType.kind == tyNone: result = "typedesc" @@ -608,7 +577,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = if prefer == preferGenericArg and t.n != nil: result = t.n.renderTree else: - result = "static[" & (if t.len > 0: typeToString(t.skipModifier) else: "") & "]" + result = "static[" & (if t.hasElementType: typeToString(t.skipModifier) else: "") & "]" if t.n != nil: result.add "(" & renderTree(t.n) & ")" of tyUserTypeClass: if t.sym != nil and t.sym.owner != nil: @@ -639,20 +608,18 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = of tyUserTypeClassInst: let body = t.base result = body.sym.name.s & "[" - for i in 1..<t.len - 1: - if i > 1: result.add(", ") - result.add(typeToString(t[i])) + for needsComma, a in t.userTypeClassInstParams: + if needsComma: result.add(", ") + result.add(typeToString(a)) result.add "]" of tyAnd: - for i, son in t: + for i, son in t.ikids: + if i > 0: result.add(" and ") result.add(typeToString(son)) - if i < t.len - 1: - result.add(" and ") of tyOr: - for i, son in t: + for i, son in t.ikids: + if i > 0: result.add(" or ") result.add(typeToString(son)) - if i < t.len - 1: - result.add(" or ") of tyNot: result = "not " & typeToString(t.elementType) of tyUntyped: @@ -665,7 +632,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = result = "typeof(" & renderTree(t.n) & ")" of tyArray: result = "array" - if t.len > 0: + if t.hasElementType: if t.indexType.kind == tyRange: result &= "[" & rangeToStr(t.indexType.n) & ", " & typeToString(t.elementType) & ']' @@ -674,26 +641,26 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = typeToString(t.elementType) & ']' of tyUncheckedArray: result = "UncheckedArray" - if t.len > 0: + if t.hasElementType: result &= "[" & typeToString(t.elementType) & ']' of tySequence: if t.sym != nil and prefer != preferResolved: result = t.sym.name.s else: result = "seq" - if t.len > 0: + if t.hasElementType: result &= "[" & typeToString(t.elementType) & ']' of tyOrdinal: result = "ordinal" - if t.len > 0: + if t.hasElementType: result &= "[" & typeToString(t.skipModifier) & ']' of tySet: result = "set" - if t.len > 0: + if t.hasElementType: result &= "[" & typeToString(t.elementType) & ']' of tyOpenArray: result = "openArray" - if t.len > 0: + if t.hasElementType: result &= "[" & typeToString(t.elementType) & ']' of tyDistinct: result = "distinct " & typeToString(t.elementType, @@ -701,38 +668,33 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = of tyIterable: # xxx factor this pattern result = "iterable" - if t.len > 0: + if t.hasElementType: result &= "[" & typeToString(t.skipModifier) & ']' of tyTuple: # we iterate over t.sons here, because t.n may be nil if t.n != nil: result = "tuple[" - assert(t.n.len == t.len) for i in 0..<t.n.len: assert(t.n[i].kind == nkSym) - result.add(t.n[i].sym.name.s & ": " & typeToString(t[i])) + result.add(t.n[i].sym.name.s & ": " & typeToString(t.n[i].sym.typ)) if i < t.n.len - 1: result.add(", ") result.add(']') - elif t.len == 0: + elif t.isEmptyTupleType: result = "tuple[]" + elif t.isSingletonTupleType: + result = "(" + for son in t.kids: + result.add(typeToString(son)) + result.add(",)") else: result = "(" - for i in 0..<t.len: - result.add(typeToString(t[i])) - if i < t.len - 1: result.add(", ") - elif t.len == 1: result.add(",") + for i, son in t.ikids: + if i > 0: result.add ", " + result.add(typeToString(son)) result.add(')') of tyPtr, tyRef, tyVar, tyLent: result = if isOutParam(t): "out " else: typeToStr[t.kind] - if t.len >= 2: - setLen(result, result.len-1) - result.add '[' - for i in 0..<t.len: - result.add(typeToString(t[i])) - if i < t.len - 1: result.add(", ") - result.add ']' - else: - result.add typeToString(t.elementType) + result.add typeToString(t.elementType) of tyRange: result = "range " if t.n != nil and t.n.kind == nkRange: @@ -751,14 +713,15 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = "proc " if tfUnresolved in t.flags: result.add "[*missing parameters*]" result.add "(" - for i in 1..<t.len: - if t.n != nil and i < t.n.len and t.n[i].kind == nkSym: - result.add(t.n[i].sym.name.s) + for i, a in t.paramTypes: + if i > FirstParamAt: result.add(", ") + let j = paramTypeToNodeIndex(i) + if t.n != nil and j < t.n.len and t.n[j].kind == nkSym: + result.add(t.n[j].sym.name.s) result.add(": ") - result.add(typeToString(t[i])) - if i < t.len - 1: result.add(", ") + result.add(typeToString(a)) result.add(')') - if t.len > 0 and t.returnType != nil: result.add(": " & typeToString(t.returnType)) + if t.returnType != nil: result.add(": " & typeToString(t.returnType)) var prag = if t.callConv == ccNimCall and tfExplicitCallConv notin t.flags: "" else: $t.callConv if not isNil(t.owner) and not isNil(t.owner.ast) and (t.owner.ast.len - 1) >= pragmasPos: let pragmasNode = t.owner.ast[pragmasPos] @@ -813,7 +776,7 @@ proc firstOrd*(conf: ConfigRef; t: PType): Int128 = of tyUInt..tyUInt64: result = Zero of tyEnum: # if basetype <> nil then return firstOrd of basetype - if t.len > 0 and t.baseClass != nil: + if t.baseClass != nil: result = firstOrd(conf, t.baseClass) else: if t.n.len > 0: @@ -827,7 +790,7 @@ proc firstOrd*(conf: ConfigRef; t: PType): Int128 = of tyUserTypeClasses: result = firstOrd(conf, last(t)) of tyOrdinal: - if t.len > 0: result = firstOrd(conf, skipModifier(t)) + if t.hasElementType: result = firstOrd(conf, skipModifier(t)) else: result = Zero internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')') @@ -923,7 +886,7 @@ proc lastOrd*(conf: ConfigRef; t: PType): Int128 = result = lastOrd(conf, last(t)) of tyProxy: result = Zero of tyOrdinal: - if t.len > 0: result = lastOrd(conf, skipModifier(t)) + if t.hasElementType: result = lastOrd(conf, skipModifier(t)) else: result = Zero internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')') @@ -1093,11 +1056,11 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool = # two tuples are equivalent iff the names, types and positions are the same; # however, both types may not have any field names (t.n may be nil) which # complicates the matter a bit. - if a.len == b.len: + if sameTupleLengths(a, b): result = true - for i in 0..<a.len: - var x = a[i] - var y = b[i] + for i, aa, bb in tupleTypePairs(a, b): + var x = aa + var y = bb if IgnoreTupleFields in c.flags: x = skipTypes(x, {tyRange, tyGenericInst, tyAlias}) y = skipTypes(y, {tyRange, tyGenericInst, tyAlias}) @@ -1184,18 +1147,16 @@ proc sameObjectTree(a, b: PNode, c: var TSameTypeClosure): bool = result = false proc sameObjectStructures(a, b: PType, c: var TSameTypeClosure): bool = - # check base types: - if a.len != b.len: return - for i in 0..<a.len: - if not sameTypeOrNilAux(a[i], b[i], c): return - if not sameObjectTree(a.n, b.n, c): return + if not sameTypeOrNilAux(a.baseClass, b.baseClass, c): return false + if not sameObjectTree(a.n, b.n, c): return false result = true proc sameChildrenAux(a, b: PType, c: var TSameTypeClosure): bool = - if a.len != b.len: return false + if not sameTupleLengths(a, b): return false + # XXX This is not tuple specific. result = true - for i in 0..<a.len: - result = sameTypeOrNilAux(a[i], b[i], c) + for _, x, y in tupleTypePairs(a, b): + result = sameTypeOrNilAux(x, y, c) if not result: return proc isGenericAlias*(t: PType): bool = @@ -1253,15 +1214,13 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = objects ie `type A[T] = SomeObject` ]# # this is required by tunique_type but makes no sense really: - if tyDistinct notin {x.kind, y.kind} and x.kind == tyGenericInst and IgnoreTupleFields notin c.flags: + if x.kind == tyGenericInst and IgnoreTupleFields notin c.flags and tyDistinct != y.kind: let lhs = x.skipGenericAlias rhs = y.skipGenericAlias if rhs.kind != tyGenericInst or lhs.base != rhs.base: return false - for i in 1..<lhs.len - 1: - let ff = rhs[i] - let aa = lhs[i] + for ff, aa in underspecifiedPairs(rhs, lhs, 1, -1): if not sameTypeAux(ff, aa, c): return false return true @@ -1279,7 +1238,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = of tyStatic, tyFromExpr: result = exprStructuralEquivalent(a.n, b.n) and sameFlags(a, b) - if result and a.len == b.len and a.len == 1: + if result and sameTupleLengths(a, b) and a.hasElementType: cycleCheck() result = sameTypeAux(a.skipModifier, b.skipModifier, c) of tyObject: @@ -1314,15 +1273,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = if result and {ExactGenericParams, ExactTypeDescValues} * c.flags != {}: result = a.sym.position == b.sym.position of tyBuiltInTypeClass: - assert a.len == 1 - assert a[0].len == 0 - assert b.len == 1 - assert b[0].len == 0 - result = a[0].kind == b[0].kind and sameFlags(a[0], b[0]) - if result and a[0].kind == tyProc and IgnoreCC notin c.flags: - let ecc = a[0].flags * {tfExplicitCallConv} - result = ecc == b[0].flags * {tfExplicitCallConv} and - (ecc == {} or a[0].callConv == b[0].callConv) + result = a.elementType.kind == b.elementType.kind and sameFlags(a.elementType, b.elementType) + if result and a.elementType.kind == tyProc and IgnoreCC notin c.flags: + let ecc = a.elementType.flags * {tfExplicitCallConv} + result = ecc == b.elementType.flags * {tfExplicitCallConv} and + (ecc == {} or a.elementType.callConv == b.elementType.callConv) of tyGenericInvocation, tyGenericBody, tySequence, tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyLent, tySink, tyUncheckedArray, tyArray, tyProc, tyVarargs, tyOrdinal, tyCompositeTypeClass, tyUserTypeClass, tyUserTypeClassInst, @@ -1418,15 +1373,6 @@ proc commonSuperclass*(a, b: PType): PType = return t y = y.baseClass -proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]], - last: TTypeKind): bool = - var a = a - for k, i in pattern.items: - if a.kind != k: return false - if i >= a.len or a[i] == nil: return false - a = a[i] - result = a.kind == last - include sizealignoffsetimpl @@ -1578,8 +1524,8 @@ proc isCompileTimeOnly*(t: PType): bool {.inline.} = proc containsCompileTimeOnly*(t: PType): bool = if isCompileTimeOnly(t): return true - for i in 0..<t.len: - if t[i] != nil and isCompileTimeOnly(t[i]): + for a in t.kids: + if a != nil and isCompileTimeOnly(a): return true return false @@ -1787,9 +1733,9 @@ proc isTupleRecursive(t: PType, cycleDetector: var IntSet): bool = of tyTuple: result = false var cycleDetectorCopy: IntSet - for i in 0..<t.len: + for a in t.kids: cycleDetectorCopy = cycleDetector - if isTupleRecursive(t[i], cycleDetectorCopy): + if isTupleRecursive(a, cycleDetectorCopy): return true of tyRef, tyPtr, tyVar, tyLent, tySink, tyArray, tyUncheckedArray, tySequence, tyDistinct: diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim index 44d38ebff..2ba644658 100644 --- a/compiler/varpartitions.nim +++ b/compiler/varpartitions.nim @@ -400,11 +400,10 @@ proc allRoots(n: PNode; result: var seq[(PSym, int)]; level: int) = if typ != nil: typ = skipTypes(typ, abstractInst) if typ.kind != tyProc: typ = nil - else: assert(typ.len == typ.n.len) for i in 1 ..< n.len: let it = n[i] - if typ != nil and i < typ.len: + if typ != nil and i < typ.n.len: assert(typ.n[i].kind == nkSym) let paramType = typ.n[i].typ if not paramType.isCompileTimeOnly and not typ.returnType.isEmptyType and diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index b58ae109f..6d0e03813 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -205,7 +205,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; # only named tuples have a node, unnamed tuples don't if t.n.isNil: result = newNodeX(nkTupleConstr) - for subType in t: + for subType in t.kids: result.add mapTypeToAst(subType, info) else: result = newNodeX(nkTupleTy) diff --git a/tests/typerel/tregionptrs.nim b/tests/typerel/tregionptrs.nim deleted file mode 100644 index 504ec1011..000000000 --- a/tests/typerel/tregionptrs.nim +++ /dev/null @@ -1,16 +0,0 @@ -discard """ - errormsg: "type mismatch: got <BPtr> but expected 'APtr = ptr[RegionA, int]'" - line: 16 -""" - -type - RegionA = object - APtr = RegionA ptr int - RegionB = object - BPtr = RegionB ptr int - -var x,xx: APtr -var y: BPtr -x = nil -x = xx -x = y |