From ea409fb15a62ff098e5de70efa780228b5d5aac0 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 23 Feb 2019 08:44:08 +0100 Subject: first steps in implementing 'owned' pointers; undocumented, do not use --- compiler/ccgexprs.nim | 8 ++++---- compiler/ccgtrav.nim | 6 +++--- compiler/ccgtypes.nim | 6 +++--- compiler/jsgen.nim | 16 +++++++++------- compiler/jstypes.nim | 2 +- compiler/semexprs.nim | 14 +++++++------- compiler/semstmts.nim | 14 +++++++------- compiler/semtypes.nim | 8 ++++---- compiler/semtypinst.nim | 2 +- compiler/sighashes.nim | 2 +- compiler/sigmatch.nim | 30 +++++++++++++++++++++++------- compiler/types.nim | 21 ++++++++++++--------- 12 files changed, 75 insertions(+), 54 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index d459f6cbf..7e0437c39 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -679,14 +679,14 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) = #if e[0].kind != nkBracketExpr: # message(e.info, warnUser, "CAME HERE " & renderTree(e)) expr(p, e.sons[0], d) - if e.sons[0].typ.skipTypes(abstractInst).kind == tyRef: + if e.sons[0].typ.skipTypes(abstractInstOwned).kind == tyRef: d.storage = OnHeap else: var a: TLoc var typ = e.sons[0].typ if typ.kind in {tyUserTypeClass, tyUserTypeClassInst} and typ.isResolvedUserTypeClass: typ = typ.lastSon - typ = typ.skipTypes(abstractInst) + typ = typ.skipTypes(abstractInstOwned) if typ.kind == tyVar and tfVarIsPtr notin typ.flags and p.module.compileToCpp and e.sons[0].kind == nkHiddenAddr: initLocExprSingleUse(p, e[0][0], d) return @@ -726,7 +726,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) = proc genAddr(p: BProc, e: PNode, d: var TLoc) = # careful 'addr(myptrToArray)' needs to get the ampersand: - if e.sons[0].typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}: + if e.sons[0].typ.skipTypes(abstractInstOwned).kind in {tyRef, tyPtr}: var a: TLoc initLocExpr(p, e.sons[0], a) putIntoDest(p, d, e, "&" & a.r, a.storage) @@ -1158,7 +1158,7 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) = let typ = a.t var b: TLoc initLoc(b, locExpr, a.lode, OnHeap) - let refType = typ.skipTypes(abstractInst) + let refType = typ.skipTypes(abstractInstOwned) assert refType.kind == tyRef let bt = refType.lastSon if sizeExpr.isNil: diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index c69bb2c80..0a2bbf93b 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -67,7 +67,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) = var p = c.p case typ.kind of tyGenericInst, tyGenericBody, tyTypeDesc, tyAlias, tyDistinct, tyInferred, - tySink: + tySink, tyOwned: genTraverseProc(c, accessor, lastSon(typ)) of tyArray: let arraySize = lengthOrd(c.p.config, typ.sons[0]) @@ -134,7 +134,7 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope = var c: TTraversalClosure var p = newProc(nil, m) result = "Marker_" & getTypeName(m, origTyp, sig) - var typ = origTyp.skipTypes(abstractInst) + var typ = origTyp.skipTypes(abstractInstOwned) let header = "static N_NIMCALL(void, $1)(void* p, NI op)" % [result] @@ -149,7 +149,7 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope = if typ.kind == tySequence: genTraverseProcSeq(c, "a".rope, typ) else: - if skipTypes(typ.sons[0], typedescInst).kind == tyArray: + if skipTypes(typ.sons[0], typedescInst+{tyOwned}).kind == tyArray: # C's arrays are broken beyond repair: genTraverseProc(c, "a".rope, typ.sons[0]) else: diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 3d00b9b0a..afe90544d 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -115,7 +115,7 @@ proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope = t = t.lastSon else: break - let typ = if typ.kind in {tyAlias, tySink}: typ.lastSon else: typ + let typ = if typ.kind in {tyAlias, tySink, tyOwned}: typ.lastSon else: typ if typ.loc.r == nil: typ.loc.r = typ.typeName & $sig else: @@ -296,7 +296,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope = of tyStatic: if typ.n != nil: result = getSimpleTypeDesc(m, lastSon typ) else: internalError(m.config, "tyStatic for getSimpleTypeDesc") - of tyGenericInst, tyAlias, tySink: + of tyGenericInst, tyAlias, tySink, tyOwned: result = getSimpleTypeDesc(m, lastSon typ) else: result = nil @@ -619,7 +619,7 @@ proc getSeqPayloadType(m: BModule; t: PType): Rope = proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope = # returns only the type's name - var t = origTyp.skipTypes(irrelevantForBackend) + var t = origTyp.skipTypes(irrelevantForBackend-{tyOwned}) if containsOrIncl(check, t.id): if not (isImportedCppType(origTyp) or isImportedCppType(t)): internalError(m.config, "cannot generate C type for: " & typeToString(origTyp)) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 53cfd5632..cad8fc990 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -927,7 +927,7 @@ proc needsNoCopy(p: PProc; y: PNode): bool = return y.kind in nodeKindsNeedNoCopy or ((mapType(y.typ) != etyBaseIndex or (y.kind == nkSym and y.sym.kind == skParam)) and (skipTypes(y.typ, abstractInst).kind in - {tyRef, tyPtr, tyLent, tyVar, tyCString, tyProc} + IntegralTypes)) + {tyRef, tyPtr, tyLent, tyVar, tyCString, tyProc, tyOwned} + IntegralTypes)) proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = var a, b: TCompRes @@ -1120,7 +1120,7 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) = proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) = var ty = skipTypes(n.sons[0].typ, abstractVarRange) - if ty.kind in {tyRef, tyPtr, tyLent}: ty = skipTypes(ty.lastSon, abstractVarRange) + if ty.kind in {tyRef, tyPtr, tyLent, tyOwned}: ty = skipTypes(ty.lastSon, abstractVarRange) case ty.kind of tyArray, tyOpenArray, tySequence, tyString, tyCString, tyVarargs: genArrayAddr(p, n, r) @@ -1340,7 +1340,8 @@ proc genArg(p: PProc, n: PNode, param: PSym, r: var TCompRes; emitted: ptr int = add(r.res, ", ") add(r.res, a.res) if emitted != nil: inc emitted[] - elif n.typ.kind in {tyVar, tyPtr, tyRef, tyLent} and n.kind in nkCallKinds and mapType(param.typ) == etyBaseIndex: + elif n.typ.kind in {tyVar, tyPtr, tyRef, tyLent, tyOwned} and + n.kind in nkCallKinds and mapType(param.typ) == etyBaseIndex: # this fixes bug #5608: let tmp = getTemp(p) add(r.res, "($1 = $2, $1[0]), $1[1]" % [tmp, a.rdLoc]) @@ -1540,7 +1541,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope = result = putToSeq("0", indirect) of tyFloat..tyFloat128: result = putToSeq("0.0", indirect) - of tyRange, tyGenericInst, tyAlias, tySink: + of tyRange, tyGenericInst, tyAlias, tySink, tyOwned: result = createVar(p, lastSon(typ), indirect) of tySet: result = putToSeq("{}", indirect) @@ -1619,7 +1620,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = if n.kind == nkEmpty: if not isIndirect(v) and - v.typ.kind in {tyVar, tyPtr, tyLent, tyRef} and mapType(p, v.typ) == etyBaseIndex: + v.typ.kind in {tyVar, tyPtr, tyLent, tyRef, tyOwned} and mapType(p, v.typ) == etyBaseIndex: lineF(p, "var $1 = null;$n", [varName]) lineF(p, "var $1_Idx = 0;$n", [varName]) else: @@ -1807,7 +1808,8 @@ proc genRepr(p: PProc, n: PNode, r: var TCompRes) = proc genOf(p: PProc, n: PNode, r: var TCompRes) = var x: TCompRes - let t = skipTypes(n.sons[2].typ, abstractVarRange+{tyRef, tyPtr, tyLent, tyTypeDesc}) + let t = skipTypes(n.sons[2].typ, + abstractVarRange+{tyRef, tyPtr, tyLent, tyTypeDesc, tyOwned}) gen(p, n.sons[1], x) if tfFinal in t.flags: r.res = "($1.m_type == $2)" % [x.res, genTypeInfo(p, t)] @@ -2172,7 +2174,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope = resultSym = prc.ast.sons[resultPos].sym let mname = mangleName(p.module, resultSym) if not isindirect(resultSym) and - resultSym.typ.kind in {tyVar, tyPtr, tyLent, tyRef} and + resultSym.typ.kind in {tyVar, tyPtr, tyLent, tyRef, tyOwned} and mapType(p, resultSym.typ) == etyBaseIndex: resultAsgn = p.indentLine(("var $# = null;$n") % [mname]) resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname]) diff --git a/compiler/jstypes.nim b/compiler/jstypes.nim index d86b09a03..743158505 100644 --- a/compiler/jstypes.nim +++ b/compiler/jstypes.nim @@ -122,7 +122,7 @@ proc genEnumInfo(p: PProc, typ: PType, name: Rope) = [name, genTypeInfo(p, typ.sons[0])]) proc genTypeInfo(p: PProc, typ: PType): Rope = - let t = typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink}) + let t = typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink, tyOwned}) result = "NTI$1" % [rope(t.id)] if containsOrIncl(p.g.typeInfoGenerated, t.id): return case t.kind diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 239dbad54..7bd40a954 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -127,7 +127,7 @@ proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus = s = s.lastSon s = skipTypes(s, abstractVar-{tyTypeDesc}) var pointers = 0 - while (d != nil) and (d.kind in {tyPtr, tyRef}) and (d.kind == s.kind): + while (d != nil) and (d.kind in {tyPtr, tyRef, tyOwned}) and (d.kind == s.kind): d = d.lastSon s = s.lastSon inc pointers @@ -224,7 +224,7 @@ proc semConv(c: PContext, n: PNode): PNode = maybeLiftType(targetType, c, n[0].info) - if targetType.kind in {tySink, tyLent}: + if targetType.kind in {tySink, tyLent, tyOwned}: let baseType = semTypeNode(c, n.sons[1], nil).skipTypes({tyTypeDesc}) let t = newTypeS(targetType.kind, c) t.rawAddSonNoPropagationOfTypeFlags baseType @@ -997,7 +997,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent, const tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass} - tyDotOpTransparent = {tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink} + tyDotOpTransparent = {tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink} proc readTypeParameter(c: PContext, typ: PType, paramName: PIdent, info: TLineInfo): PNode = @@ -1150,7 +1150,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = p = p.next if p != nil and p.selfSym != nil: var ty = skipTypes(p.selfSym.typ, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, - tyAlias, tySink}) + tyAlias, tySink, tyOwned}) while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct}) var check: PNode = nil if ty.kind == tyObject: @@ -1282,7 +1282,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = return nil if ty.kind in tyUserTypeClasses and ty.isResolvedUserTypeClass: ty = ty.lastSon - ty = skipTypes(ty, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink}) + ty = skipTypes(ty, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink}) while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct}) var check: PNode = nil if ty.kind == tyObject: @@ -1353,7 +1353,7 @@ proc semDeref(c: PContext, n: PNode): PNode = checkSonsLen(n, 1, c.config) n.sons[0] = semExprWithType(c, n.sons[0]) result = n - var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyAlias, tySink}) + var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyAlias, tySink, tyOwned}) case t.kind of tyRef, tyPtr: n.typ = t.lastSon else: result = nil @@ -1372,7 +1372,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode = # make sure we don't evaluate generic macros/templates n.sons[0] = semExprWithType(c, n.sons[0], {efNoEvaluateGeneric}) - var arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyUserTypeClassInst, + var arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyUserTypeClassInst, tyOwned, tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink}) if arr.kind == tyStatic: if arr.base.kind == tyNone: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3827da220..363049672 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -391,18 +391,18 @@ proc makeDeref(n: PNode): PNode = var t = n.typ if t.kind in tyUserTypeClasses and t.isResolvedUserTypeClass: t = t.lastSon - t = skipTypes(t, {tyGenericInst, tyAlias, tySink}) + t = skipTypes(t, {tyGenericInst, tyAlias, tySink, tyOwned}) result = n if t.kind in {tyVar, tyLent}: result = newNodeIT(nkHiddenDeref, n.info, t.sons[0]) addSon(result, n) - t = skipTypes(t.sons[0], {tyGenericInst, tyAlias, tySink}) + t = skipTypes(t.sons[0], {tyGenericInst, tyAlias, tySink, tyOwned}) while t.kind in {tyPtr, tyRef}: var a = result let baseTyp = t.lastSon result = newNodeIT(nkHiddenDeref, n.info, baseTyp) addSon(result, a) - t = skipTypes(baseTyp, {tyGenericInst, tyAlias, tySink}) + t = skipTypes(baseTyp, {tyGenericInst, tyAlias, tySink, tyOwned}) proc fillPartialObject(c: PContext; n: PNode; typ: PType) = if n.len == 2: @@ -908,7 +908,7 @@ proc semRaise(c: PContext, n: PNode): PNode = n[0] = semExprWithType(c, n[0]) var typ = n[0].typ if not isImportedException(typ, c.config): - typ = typ.skipTypes({tyAlias, tyGenericInst}) + typ = typ.skipTypes({tyAlias, tyGenericInst, tyOwned}) if typ.kind != tyRef: localError(c.config, n.info, errExprCannotBeRaised) if typ.len > 0 and not isException(typ.lastSon): @@ -1059,7 +1059,7 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) = of tyPtr, tyRef, tyVar, tyLent: if t.base.kind == tyGenericParam: return true return traverseSubTypes(c, t.base) - of tyDistinct, tyAlias, tySink: + of tyDistinct, tyAlias, tySink, tyOwned: return traverseSubTypes(c, t.lastSon) of tyGenericInst: internalAssert c.config, false @@ -1180,7 +1180,7 @@ proc checkForMetaFields(c: PContext; n: PNode) = let t = n.sym.typ case t.kind of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyLent, tyPtr, tyRef, - tyProc, tyGenericInvocation, tyGenericInst, tyAlias, tySink: + tyProc, tyGenericInvocation, tyGenericInst, tyAlias, tySink, tyOwned: let start = ord(t.kind in {tyGenericInvocation, tyGenericInst}) for i in start ..< t.len: checkMeta(c, n, t.sons[i]) @@ -1636,7 +1636,7 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) = if t != nil and t.kind == tyGenericInvocation: var x = skipTypes(t.sons[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst, tyGenericInvocation, tyGenericBody, - tyAlias, tySink}) + tyAlias, tySink, tyOwned}) if x.kind == tyObject and t.len-1 == n.sons[genericParamsPos].len: foundObj = true x.methods.add((col,s)) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index f570cdffa..d4fcea0b4 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -750,7 +750,7 @@ proc skipGenericInvocation(t: PType): PType {.inline.} = result = t if result.kind == tyGenericInvocation: result = result.sons[0] - while result.kind in {tyGenericInst, tyGenericBody, tyRef, tyPtr, tyAlias, tySink}: + while result.kind in {tyGenericInst, tyGenericBody, tyRef, tyPtr, tyAlias, tySink, tyOwned}: result = lastSon(result) proc addInheritedFields(c: PContext, check: var IntSet, pos: var int, @@ -955,7 +955,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, # disable the bindOnce behavior for the type class result = liftingWalk(paramType.base, true) - of tyAlias: + of tyAlias, tyOwned: result = liftingWalk(paramType.base) of tySequence, tySet, tyArray, tyOpenArray, @@ -1528,7 +1528,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = semRangeAux(c, n, prev) elif n[0].kind == nkNilLit and n.len == 2: result = semTypeNode(c, n.sons[1], prev) - if result.skipTypes({tyGenericInst, tyAlias, tySink}).kind in NilableTypes+GenericTypes: + if result.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).kind in NilableTypes+GenericTypes: if tfNotNil in result.flags: result = freshType(result, prev) result.flags.excl(tfNotNil) @@ -1556,7 +1556,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = case n.len of 3: result = semTypeNode(c, n.sons[1], prev) - if result.skipTypes({tyGenericInst, tyAlias, tySink}).kind in NilableTypes+GenericTypes+{tyForward} and + if result.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).kind in NilableTypes+GenericTypes+{tyForward} and n.sons[2].kind == nkNilLit: result = freshType(result, prev) result.flags.incl(tfNotNil) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index ceabd8e60..002f4f402 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -574,7 +574,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = var r = replaceTypeVarsT(cl, result.sons[i]) if result.kind == tyObject: # carefully coded to not skip the precious tyGenericInst: - let r2 = r.skipTypes({tyAlias, tySink}) + let r2 = r.skipTypes({tyAlias, tySink, tyOwned}) if r2.kind in {tyPtr, tyRef}: r = skipTypes(r2, {tyPtr, tyRef}) result.sons[i] = r diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim index 3096d94a0..95240867f 100644 --- a/compiler/sighashes.nim +++ b/compiler/sighashes.nim @@ -165,7 +165,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) = c.hashType t.sons[i], flags else: c.hashType t.lastSon, flags - of tyAlias, tySink, tyUserTypeClasses, tyInferred: + of tyAlias, tySink, tyUserTypeClasses, tyInferred, tyOwned: c.hashType t.lastSon, flags of tyBool, tyChar, tyInt..tyUInt64: # no canonicalization for integral types, so that e.g. ``pid_t`` is diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 3eaac06e5..cb71c1c81 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -188,7 +188,7 @@ proc sumGeneric(t: PType): int = case t.kind of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyUncheckedArray, tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody, - tyLent: + tyLent, tyOwned: t = t.lastSon inc result of tyOr: @@ -476,7 +476,7 @@ proc skipToObject(t: PType; skipped: var SkippedPtr): PType = inc ptrs skipped = skippedPtr r = r.lastSon - of tyGenericBody, tyGenericInst, tyAlias, tySink: + of tyGenericBody, tyGenericInst, tyAlias, tySink, tyOwned: r = r.lastSon else: break @@ -919,7 +919,8 @@ proc inferStaticsInRange(c: var TCandidate, doInferStatic(lowerBound, upperBound.intVal + 1 - lengthOrd(c.c.config, concrete)) template subtypeCheck() = - if result <= isSubrange and f.lastSon.skipTypes(abstractInst).kind in {tyRef, tyPtr, tyVar, tyLent}: + if result <= isSubrange and f.lastSon.skipTypes(abstractInst).kind in { + tyRef, tyPtr, tyVar, tyLent, tyOwned}: result = isNone proc isCovariantPtr(c: var TCandidate, f, a: PType): bool = @@ -927,11 +928,11 @@ proc isCovariantPtr(c: var TCandidate, f, a: PType): bool = assert f.kind == a.kind template baseTypesCheck(lhs, rhs: PType): bool = - lhs.kind notin {tyPtr, tyRef, tyVar, tyLent} and + lhs.kind notin {tyPtr, tyRef, tyVar, tyLent, tyOwned} and typeRel(c, lhs, rhs, {trNoCovariance}) == isSubtype case f.kind - of tyRef, tyPtr: + of tyRef, tyPtr, tyOwned: return baseTypesCheck(f.base, a.base) of tyGenericInst: let body = f.base @@ -962,6 +963,9 @@ when false: of tyFloat64: greater({tyFloat128}) else: discard +template skipOwned(a) = + if a.kind == tyOwned: a = a.skipTypes({tyOwned, tyGenericInst}) + proc typeRelImpl(c: var TCandidate, f, aOrig: PType, flags: TTypeRelFlags = {}): TTypeRelation = # typeRel can be used to establish various relationships between types: @@ -1279,6 +1283,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, #internalError("forward type in typeRel()") result = isNone of tyNil: + skipOwned(a) if a.kind == f.kind: result = isEqual of tyTuple: if a.kind == tyTuple: result = recordRel(c, f, a) @@ -1298,7 +1303,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, #elif f.base.kind == tyAnything: result = isGeneric # issue 4435 elif c.coerceDistincts: result = typeRel(c, f.base, a) elif a.kind == tyNil and f.base.kind in NilableTypes: - result = f.allowsNil + result = f.allowsNil # XXX remove this typing rule, it is not in the spec elif c.coerceDistincts: result = typeRel(c, f.base, a) of tySet: if a.kind == tySet: @@ -1309,6 +1314,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, if result <= isConvertible: result = isNone # BUGFIX! of tyPtr, tyRef: + skipOwned(a) if a.kind == f.kind: # ptr[R, T] can be passed to ptr[T], but not the other way round: if a.len < f.len: return isNone @@ -1322,10 +1328,18 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, elif a.kind == tyNil: result = f.allowsNil else: discard of tyProc: + skipOwned(a) result = procTypeRel(c, f, a) if result != isNone and tfNotNil in f.flags and tfNotNil notin a.flags: result = isNilConversion + of tyOwned: + case a.kind + of tyOwned: + result = typeRel(c, lastSon(f), lastSon(a)) + of tyNil: result = f.allowsNil + else: discard of tyPointer: + skipOwned(a) case a.kind of tyPointer: if tfNotNil in f.flags and tfNotNil notin a.flags: @@ -1917,8 +1931,10 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, # this will be done earlier - we just have to # make sure that static types enter here - # XXX: weaken tyGenericParam and call it tyGenericPlaceholder + # Zahary: weaken tyGenericParam and call it tyGenericPlaceholder # and finally start using tyTypedesc for generic types properly. + # Araq: This would only shift the problems around, in 'proc p[T](x: T)' + # the T is NOT a typedesc. if a.kind == tyGenericParam and tfWildcard in a.flags: a.assignType(f) # put(m.bindings, f, a) diff --git a/compiler/types.nim b/compiler/types.nim index 91076fae3..0e2c3b651 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -52,20 +52,21 @@ const # TODO: Remove tyTypeDesc from each abstractX and (where necessary) # replace with typedescX abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal, - tyTypeDesc, tyAlias, tyInferred, tySink, tyLent} + tyTypeDesc, tyAlias, tyInferred, tySink, tyLent, tyOwned} abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, - tyAlias, tyInferred, tySink, tyLent} + tyAlias, tyInferred, tySink, tyLent, tyOwned} abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal, tyTypeDesc, - tyAlias, tyInferred, tySink} + tyAlias, tyInferred, tySink, tyOwned} abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias, tyInferred, tySink} abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias, tyInferred, tySink} + abstractInstOwned* = abstractInst + {tyOwned} skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc, tyAlias, - tyInferred, tySink, tyLent} + tyInferred, tySink, tyLent, tyOwned} # typedescX is used if we're sure tyTypeDesc should be included (or skipped) typedescPtrs* = abstractPtrs + {tyTypeDesc} - typedescInst* = abstractInst + {tyTypeDesc} + typedescInst* = abstractInst + {tyTypeDesc, tyOwned} type TTypeFieldResult* = enum @@ -323,7 +324,7 @@ proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool = result = false if typ == nil: return if tfAcyclic in typ.flags: return - var t = skipTypes(typ, abstractInst-{tyTypeDesc}) + var t = skipTypes(typ, abstractInst+{tyOwned}-{tyTypeDesc}) if tfAcyclic in t.flags: return case t.kind of tyTuple, tyObject, tyRef, tySequence, tyArray, tyOpenArray, tyVarargs: @@ -399,8 +400,8 @@ const "int", "int8", "int16", "int32", "int64", "float", "float32", "float64", "float128", "uint", "uint8", "uint16", "uint32", "uint64", - "opt", "sink", - "lent ", "varargs[$1]", "UncheckedArray[$1]", "Error Type", + "owned", "sink", + "lent", "varargs[$1]", "UncheckedArray[$1]", "Error Type", "BuiltInTypeClass", "UserTypeClass", "UserTypeClassInst", "CompositeTypeClass", "inferred", "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor", @@ -622,6 +623,8 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = result = typeToStr[t.kind] % typeToString(t.sons[0]) of tySink: result = "sink " & typeToString(t.sons[0]) + of tyOwned: + result = "owned " & typeToString(t.sons[0]) else: result = typeToStr[t.kind] result.addTypeFlags(t) @@ -1328,7 +1331,7 @@ proc baseOfDistinct*(t: PType): PType = result = copyType(t, t.owner, false) var parent: PType = nil var it = result - while it.kind in {tyPtr, tyRef}: + while it.kind in {tyPtr, tyRef, tyOwned}: parent = it it = it.lastSon if it.kind == tyDistinct and parent != nil: -- cgit 1.4.1-2-gfad0