first steps in implementing 'owned' pointers; undocumented, do not use

This commit is contained in:
Andreas Rumpf 2019-02-23 08:44:08 +01:00
commit ea409fb15a
12 changed files with 75 additions and 54 deletions

View file

@ -679,14 +679,14 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
#if e[0].kind != nkBracketExpr: #if e[0].kind != nkBracketExpr:
# message(e.info, warnUser, "CAME HERE " & renderTree(e)) # message(e.info, warnUser, "CAME HERE " & renderTree(e))
expr(p, e.sons[0], d) 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 d.storage = OnHeap
else: else:
var a: TLoc var a: TLoc
var typ = e.sons[0].typ var typ = e.sons[0].typ
if typ.kind in {tyUserTypeClass, tyUserTypeClassInst} and typ.isResolvedUserTypeClass: if typ.kind in {tyUserTypeClass, tyUserTypeClassInst} and typ.isResolvedUserTypeClass:
typ = typ.lastSon 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: 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) initLocExprSingleUse(p, e[0][0], d)
return 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) = proc genAddr(p: BProc, e: PNode, d: var TLoc) =
# careful 'addr(myptrToArray)' needs to get the ampersand: # 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 var a: TLoc
initLocExpr(p, e.sons[0], a) initLocExpr(p, e.sons[0], a)
putIntoDest(p, d, e, "&" & a.r, a.storage) putIntoDest(p, d, e, "&" & a.r, a.storage)
@ -1158,7 +1158,7 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
let typ = a.t let typ = a.t
var b: TLoc var b: TLoc
initLoc(b, locExpr, a.lode, OnHeap) initLoc(b, locExpr, a.lode, OnHeap)
let refType = typ.skipTypes(abstractInst) let refType = typ.skipTypes(abstractInstOwned)
assert refType.kind == tyRef assert refType.kind == tyRef
let bt = refType.lastSon let bt = refType.lastSon
if sizeExpr.isNil: if sizeExpr.isNil:

View file

@ -67,7 +67,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
var p = c.p var p = c.p
case typ.kind case typ.kind
of tyGenericInst, tyGenericBody, tyTypeDesc, tyAlias, tyDistinct, tyInferred, of tyGenericInst, tyGenericBody, tyTypeDesc, tyAlias, tyDistinct, tyInferred,
tySink: tySink, tyOwned:
genTraverseProc(c, accessor, lastSon(typ)) genTraverseProc(c, accessor, lastSon(typ))
of tyArray: of tyArray:
let arraySize = lengthOrd(c.p.config, typ.sons[0]) 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 c: TTraversalClosure
var p = newProc(nil, m) var p = newProc(nil, m)
result = "Marker_" & getTypeName(m, origTyp, sig) 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] 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: if typ.kind == tySequence:
genTraverseProcSeq(c, "a".rope, typ) genTraverseProcSeq(c, "a".rope, typ)
else: 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: # C's arrays are broken beyond repair:
genTraverseProc(c, "a".rope, typ.sons[0]) genTraverseProc(c, "a".rope, typ.sons[0])
else: else:

View file

@ -115,7 +115,7 @@ proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
t = t.lastSon t = t.lastSon
else: else:
break 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: if typ.loc.r == nil:
typ.loc.r = typ.typeName & $sig typ.loc.r = typ.typeName & $sig
else: else:
@ -296,7 +296,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
of tyStatic: of tyStatic:
if typ.n != nil: result = getSimpleTypeDesc(m, lastSon typ) if typ.n != nil: result = getSimpleTypeDesc(m, lastSon typ)
else: internalError(m.config, "tyStatic for getSimpleTypeDesc") else: internalError(m.config, "tyStatic for getSimpleTypeDesc")
of tyGenericInst, tyAlias, tySink: of tyGenericInst, tyAlias, tySink, tyOwned:
result = getSimpleTypeDesc(m, lastSon typ) result = getSimpleTypeDesc(m, lastSon typ)
else: result = nil else: result = nil
@ -619,7 +619,7 @@ proc getSeqPayloadType(m: BModule; t: PType): Rope =
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope = proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
# returns only the type's name # returns only the type's name
var t = origTyp.skipTypes(irrelevantForBackend) var t = origTyp.skipTypes(irrelevantForBackend-{tyOwned})
if containsOrIncl(check, t.id): if containsOrIncl(check, t.id):
if not (isImportedCppType(origTyp) or isImportedCppType(t)): if not (isImportedCppType(origTyp) or isImportedCppType(t)):
internalError(m.config, "cannot generate C type for: " & typeToString(origTyp)) internalError(m.config, "cannot generate C type for: " & typeToString(origTyp))

View file

@ -927,7 +927,7 @@ proc needsNoCopy(p: PProc; y: PNode): bool =
return y.kind in nodeKindsNeedNoCopy or return y.kind in nodeKindsNeedNoCopy or
((mapType(y.typ) != etyBaseIndex or (y.kind == nkSym and y.sym.kind == skParam)) and ((mapType(y.typ) != etyBaseIndex or (y.kind == nkSym and y.sym.kind == skParam)) and
(skipTypes(y.typ, abstractInst).kind in (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) = proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
var a, b: TCompRes 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) = proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) =
var ty = skipTypes(n.sons[0].typ, abstractVarRange) 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 case ty.kind
of tyArray, tyOpenArray, tySequence, tyString, tyCString, tyVarargs: of tyArray, tyOpenArray, tySequence, tyString, tyCString, tyVarargs:
genArrayAddr(p, n, r) 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, ", ")
add(r.res, a.res) add(r.res, a.res)
if emitted != nil: inc emitted[] 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: # this fixes bug #5608:
let tmp = getTemp(p) let tmp = getTemp(p)
add(r.res, "($1 = $2, $1[0]), $1[1]" % [tmp, a.rdLoc]) 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) result = putToSeq("0", indirect)
of tyFloat..tyFloat128: of tyFloat..tyFloat128:
result = putToSeq("0.0", indirect) result = putToSeq("0.0", indirect)
of tyRange, tyGenericInst, tyAlias, tySink: of tyRange, tyGenericInst, tyAlias, tySink, tyOwned:
result = createVar(p, lastSon(typ), indirect) result = createVar(p, lastSon(typ), indirect)
of tySet: of tySet:
result = putToSeq("{}", indirect) result = putToSeq("{}", indirect)
@ -1619,7 +1620,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
if n.kind == nkEmpty: if n.kind == nkEmpty:
if not isIndirect(v) and 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 = null;$n", [varName])
lineF(p, "var $1_Idx = 0;$n", [varName]) lineF(p, "var $1_Idx = 0;$n", [varName])
else: else:
@ -1807,7 +1808,8 @@ proc genRepr(p: PProc, n: PNode, r: var TCompRes) =
proc genOf(p: PProc, n: PNode, r: var TCompRes) = proc genOf(p: PProc, n: PNode, r: var TCompRes) =
var x: 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) gen(p, n.sons[1], x)
if tfFinal in t.flags: if tfFinal in t.flags:
r.res = "($1.m_type == $2)" % [x.res, genTypeInfo(p, t)] 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 resultSym = prc.ast.sons[resultPos].sym
let mname = mangleName(p.module, resultSym) let mname = mangleName(p.module, resultSym)
if not isindirect(resultSym) and 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: mapType(p, resultSym.typ) == etyBaseIndex:
resultAsgn = p.indentLine(("var $# = null;$n") % [mname]) resultAsgn = p.indentLine(("var $# = null;$n") % [mname])
resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname]) resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname])

View file

@ -122,7 +122,7 @@ proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
[name, genTypeInfo(p, typ.sons[0])]) [name, genTypeInfo(p, typ.sons[0])])
proc genTypeInfo(p: PProc, typ: PType): Rope = 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)] result = "NTI$1" % [rope(t.id)]
if containsOrIncl(p.g.typeInfoGenerated, t.id): return if containsOrIncl(p.g.typeInfoGenerated, t.id): return
case t.kind case t.kind

View file

@ -127,7 +127,7 @@ proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus =
s = s.lastSon s = s.lastSon
s = skipTypes(s, abstractVar-{tyTypeDesc}) s = skipTypes(s, abstractVar-{tyTypeDesc})
var pointers = 0 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 d = d.lastSon
s = s.lastSon s = s.lastSon
inc pointers inc pointers
@ -224,7 +224,7 @@ proc semConv(c: PContext, n: PNode): PNode =
maybeLiftType(targetType, c, n[0].info) 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 baseType = semTypeNode(c, n.sons[1], nil).skipTypes({tyTypeDesc})
let t = newTypeS(targetType.kind, c) let t = newTypeS(targetType.kind, c)
t.rawAddSonNoPropagationOfTypeFlags baseType t.rawAddSonNoPropagationOfTypeFlags baseType
@ -997,7 +997,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
const const
tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass} tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass}
tyDotOpTransparent = {tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink} tyDotOpTransparent = {tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink}
proc readTypeParameter(c: PContext, typ: PType, proc readTypeParameter(c: PContext, typ: PType,
paramName: PIdent, info: TLineInfo): PNode = paramName: PIdent, info: TLineInfo): PNode =
@ -1150,7 +1150,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
p = p.next p = p.next
if p != nil and p.selfSym != nil: if p != nil and p.selfSym != nil:
var ty = skipTypes(p.selfSym.typ, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, 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}) while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct})
var check: PNode = nil var check: PNode = nil
if ty.kind == tyObject: if ty.kind == tyObject:
@ -1282,7 +1282,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
return nil return nil
if ty.kind in tyUserTypeClasses and ty.isResolvedUserTypeClass: if ty.kind in tyUserTypeClasses and ty.isResolvedUserTypeClass:
ty = ty.lastSon 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}) while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct})
var check: PNode = nil var check: PNode = nil
if ty.kind == tyObject: if ty.kind == tyObject:
@ -1353,7 +1353,7 @@ proc semDeref(c: PContext, n: PNode): PNode =
checkSonsLen(n, 1, c.config) checkSonsLen(n, 1, c.config)
n.sons[0] = semExprWithType(c, n.sons[0]) n.sons[0] = semExprWithType(c, n.sons[0])
result = n 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 case t.kind
of tyRef, tyPtr: n.typ = t.lastSon of tyRef, tyPtr: n.typ = t.lastSon
else: result = nil 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 # make sure we don't evaluate generic macros/templates
n.sons[0] = semExprWithType(c, n.sons[0], n.sons[0] = semExprWithType(c, n.sons[0],
{efNoEvaluateGeneric}) {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}) tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink})
if arr.kind == tyStatic: if arr.kind == tyStatic:
if arr.base.kind == tyNone: if arr.base.kind == tyNone:

View file

@ -391,18 +391,18 @@ proc makeDeref(n: PNode): PNode =
var t = n.typ var t = n.typ
if t.kind in tyUserTypeClasses and t.isResolvedUserTypeClass: if t.kind in tyUserTypeClasses and t.isResolvedUserTypeClass:
t = t.lastSon t = t.lastSon
t = skipTypes(t, {tyGenericInst, tyAlias, tySink}) t = skipTypes(t, {tyGenericInst, tyAlias, tySink, tyOwned})
result = n result = n
if t.kind in {tyVar, tyLent}: if t.kind in {tyVar, tyLent}:
result = newNodeIT(nkHiddenDeref, n.info, t.sons[0]) result = newNodeIT(nkHiddenDeref, n.info, t.sons[0])
addSon(result, n) 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}: while t.kind in {tyPtr, tyRef}:
var a = result var a = result
let baseTyp = t.lastSon let baseTyp = t.lastSon
result = newNodeIT(nkHiddenDeref, n.info, baseTyp) result = newNodeIT(nkHiddenDeref, n.info, baseTyp)
addSon(result, a) addSon(result, a)
t = skipTypes(baseTyp, {tyGenericInst, tyAlias, tySink}) t = skipTypes(baseTyp, {tyGenericInst, tyAlias, tySink, tyOwned})
proc fillPartialObject(c: PContext; n: PNode; typ: PType) = proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
if n.len == 2: if n.len == 2:
@ -908,7 +908,7 @@ proc semRaise(c: PContext, n: PNode): PNode =
n[0] = semExprWithType(c, n[0]) n[0] = semExprWithType(c, n[0])
var typ = n[0].typ var typ = n[0].typ
if not isImportedException(typ, c.config): if not isImportedException(typ, c.config):
typ = typ.skipTypes({tyAlias, tyGenericInst}) typ = typ.skipTypes({tyAlias, tyGenericInst, tyOwned})
if typ.kind != tyRef: if typ.kind != tyRef:
localError(c.config, n.info, errExprCannotBeRaised) localError(c.config, n.info, errExprCannotBeRaised)
if typ.len > 0 and not isException(typ.lastSon): if typ.len > 0 and not isException(typ.lastSon):
@ -1059,7 +1059,7 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) =
of tyPtr, tyRef, tyVar, tyLent: of tyPtr, tyRef, tyVar, tyLent:
if t.base.kind == tyGenericParam: return true if t.base.kind == tyGenericParam: return true
return traverseSubTypes(c, t.base) return traverseSubTypes(c, t.base)
of tyDistinct, tyAlias, tySink: of tyDistinct, tyAlias, tySink, tyOwned:
return traverseSubTypes(c, t.lastSon) return traverseSubTypes(c, t.lastSon)
of tyGenericInst: of tyGenericInst:
internalAssert c.config, false internalAssert c.config, false
@ -1180,7 +1180,7 @@ proc checkForMetaFields(c: PContext; n: PNode) =
let t = n.sym.typ let t = n.sym.typ
case t.kind case t.kind
of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyLent, tyPtr, tyRef, 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}) let start = ord(t.kind in {tyGenericInvocation, tyGenericInst})
for i in start ..< t.len: for i in start ..< t.len:
checkMeta(c, n, t.sons[i]) 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: if t != nil and t.kind == tyGenericInvocation:
var x = skipTypes(t.sons[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst, var x = skipTypes(t.sons[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst,
tyGenericInvocation, tyGenericBody, tyGenericInvocation, tyGenericBody,
tyAlias, tySink}) tyAlias, tySink, tyOwned})
if x.kind == tyObject and t.len-1 == n.sons[genericParamsPos].len: if x.kind == tyObject and t.len-1 == n.sons[genericParamsPos].len:
foundObj = true foundObj = true
x.methods.add((col,s)) x.methods.add((col,s))

View file

@ -750,7 +750,7 @@ proc skipGenericInvocation(t: PType): PType {.inline.} =
result = t result = t
if result.kind == tyGenericInvocation: if result.kind == tyGenericInvocation:
result = result.sons[0] 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) result = lastSon(result)
proc addInheritedFields(c: PContext, check: var IntSet, pos: var int, 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 # disable the bindOnce behavior for the type class
result = liftingWalk(paramType.base, true) result = liftingWalk(paramType.base, true)
of tyAlias: of tyAlias, tyOwned:
result = liftingWalk(paramType.base) result = liftingWalk(paramType.base)
of tySequence, tySet, tyArray, tyOpenArray, of tySequence, tySet, tyArray, tyOpenArray,
@ -1528,7 +1528,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = semRangeAux(c, n, prev) result = semRangeAux(c, n, prev)
elif n[0].kind == nkNilLit and n.len == 2: elif n[0].kind == nkNilLit and n.len == 2:
result = semTypeNode(c, n.sons[1], prev) 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: if tfNotNil in result.flags:
result = freshType(result, prev) result = freshType(result, prev)
result.flags.excl(tfNotNil) result.flags.excl(tfNotNil)
@ -1556,7 +1556,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
case n.len case n.len
of 3: of 3:
result = semTypeNode(c, n.sons[1], prev) 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: n.sons[2].kind == nkNilLit:
result = freshType(result, prev) result = freshType(result, prev)
result.flags.incl(tfNotNil) result.flags.incl(tfNotNil)

View file

@ -574,7 +574,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
var r = replaceTypeVarsT(cl, result.sons[i]) var r = replaceTypeVarsT(cl, result.sons[i])
if result.kind == tyObject: if result.kind == tyObject:
# carefully coded to not skip the precious tyGenericInst: # 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}: if r2.kind in {tyPtr, tyRef}:
r = skipTypes(r2, {tyPtr, tyRef}) r = skipTypes(r2, {tyPtr, tyRef})
result.sons[i] = r result.sons[i] = r

View file

@ -165,7 +165,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
c.hashType t.sons[i], flags c.hashType t.sons[i], flags
else: else:
c.hashType t.lastSon, flags c.hashType t.lastSon, flags
of tyAlias, tySink, tyUserTypeClasses, tyInferred: of tyAlias, tySink, tyUserTypeClasses, tyInferred, tyOwned:
c.hashType t.lastSon, flags c.hashType t.lastSon, flags
of tyBool, tyChar, tyInt..tyUInt64: of tyBool, tyChar, tyInt..tyUInt64:
# no canonicalization for integral types, so that e.g. ``pid_t`` is # no canonicalization for integral types, so that e.g. ``pid_t`` is

View file

@ -188,7 +188,7 @@ proc sumGeneric(t: PType): int =
case t.kind case t.kind
of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyUncheckedArray, of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyUncheckedArray,
tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody, tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody,
tyLent: tyLent, tyOwned:
t = t.lastSon t = t.lastSon
inc result inc result
of tyOr: of tyOr:
@ -476,7 +476,7 @@ proc skipToObject(t: PType; skipped: var SkippedPtr): PType =
inc ptrs inc ptrs
skipped = skippedPtr skipped = skippedPtr
r = r.lastSon r = r.lastSon
of tyGenericBody, tyGenericInst, tyAlias, tySink: of tyGenericBody, tyGenericInst, tyAlias, tySink, tyOwned:
r = r.lastSon r = r.lastSon
else: else:
break break
@ -919,7 +919,8 @@ proc inferStaticsInRange(c: var TCandidate,
doInferStatic(lowerBound, upperBound.intVal + 1 - lengthOrd(c.c.config, concrete)) doInferStatic(lowerBound, upperBound.intVal + 1 - lengthOrd(c.c.config, concrete))
template subtypeCheck() = 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 result = isNone
proc isCovariantPtr(c: var TCandidate, f, a: PType): bool = 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 assert f.kind == a.kind
template baseTypesCheck(lhs, rhs: PType): bool = 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 typeRel(c, lhs, rhs, {trNoCovariance}) == isSubtype
case f.kind case f.kind
of tyRef, tyPtr: of tyRef, tyPtr, tyOwned:
return baseTypesCheck(f.base, a.base) return baseTypesCheck(f.base, a.base)
of tyGenericInst: of tyGenericInst:
let body = f.base let body = f.base
@ -962,6 +963,9 @@ when false:
of tyFloat64: greater({tyFloat128}) of tyFloat64: greater({tyFloat128})
else: discard else: discard
template skipOwned(a) =
if a.kind == tyOwned: a = a.skipTypes({tyOwned, tyGenericInst})
proc typeRelImpl(c: var TCandidate, f, aOrig: PType, proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
flags: TTypeRelFlags = {}): TTypeRelation = flags: TTypeRelFlags = {}): TTypeRelation =
# typeRel can be used to establish various relationships between types: # 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()") #internalError("forward type in typeRel()")
result = isNone result = isNone
of tyNil: of tyNil:
skipOwned(a)
if a.kind == f.kind: result = isEqual if a.kind == f.kind: result = isEqual
of tyTuple: of tyTuple:
if a.kind == tyTuple: result = recordRel(c, f, a) 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 f.base.kind == tyAnything: result = isGeneric # issue 4435
elif c.coerceDistincts: result = typeRel(c, f.base, a) elif c.coerceDistincts: result = typeRel(c, f.base, a)
elif a.kind == tyNil and f.base.kind in NilableTypes: 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) elif c.coerceDistincts: result = typeRel(c, f.base, a)
of tySet: of tySet:
if a.kind == tySet: if a.kind == tySet:
@ -1309,6 +1314,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
if result <= isConvertible: if result <= isConvertible:
result = isNone # BUGFIX! result = isNone # BUGFIX!
of tyPtr, tyRef: of tyPtr, tyRef:
skipOwned(a)
if a.kind == f.kind: if a.kind == f.kind:
# ptr[R, T] can be passed to ptr[T], but not the other way round: # ptr[R, T] can be passed to ptr[T], but not the other way round:
if a.len < f.len: return isNone 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 elif a.kind == tyNil: result = f.allowsNil
else: discard else: discard
of tyProc: of tyProc:
skipOwned(a)
result = procTypeRel(c, f, a) result = procTypeRel(c, f, a)
if result != isNone and tfNotNil in f.flags and tfNotNil notin a.flags: if result != isNone and tfNotNil in f.flags and tfNotNil notin a.flags:
result = isNilConversion 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: of tyPointer:
skipOwned(a)
case a.kind case a.kind
of tyPointer: of tyPointer:
if tfNotNil in f.flags and tfNotNil notin a.flags: 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 # this will be done earlier - we just have to
# make sure that static types enter here # 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. # 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: if a.kind == tyGenericParam and tfWildcard in a.flags:
a.assignType(f) a.assignType(f)
# put(m.bindings, f, a) # put(m.bindings, f, a)

View file

@ -52,20 +52,21 @@ const
# TODO: Remove tyTypeDesc from each abstractX and (where necessary) # TODO: Remove tyTypeDesc from each abstractX and (where necessary)
# replace with typedescX # replace with typedescX
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal, abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
tyTypeDesc, tyAlias, tyInferred, tySink, tyLent} tyTypeDesc, tyAlias, tyInferred, tySink, tyLent, tyOwned}
abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc,
tyAlias, tyInferred, tySink, tyLent} tyAlias, tyInferred, tySink, tyLent, tyOwned}
abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal, tyTypeDesc, abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal, tyTypeDesc,
tyAlias, tyInferred, tySink} tyAlias, tyInferred, tySink, tyOwned}
abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal, abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
tyTypeDesc, tyAlias, tyInferred, tySink} tyTypeDesc, tyAlias, tyInferred, tySink}
abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias, abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias,
tyInferred, tySink} tyInferred, tySink}
abstractInstOwned* = abstractInst + {tyOwned}
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc, tyAlias, 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) # typedescX is used if we're sure tyTypeDesc should be included (or skipped)
typedescPtrs* = abstractPtrs + {tyTypeDesc} typedescPtrs* = abstractPtrs + {tyTypeDesc}
typedescInst* = abstractInst + {tyTypeDesc} typedescInst* = abstractInst + {tyTypeDesc, tyOwned}
type type
TTypeFieldResult* = enum TTypeFieldResult* = enum
@ -323,7 +324,7 @@ proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool =
result = false result = false
if typ == nil: return if typ == nil: return
if tfAcyclic in typ.flags: 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 if tfAcyclic in t.flags: return
case t.kind case t.kind
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyOpenArray, tyVarargs: of tyTuple, tyObject, tyRef, tySequence, tyArray, tyOpenArray, tyVarargs:
@ -399,8 +400,8 @@ const
"int", "int8", "int16", "int32", "int64", "int", "int8", "int16", "int32", "int64",
"float", "float32", "float64", "float128", "float", "float32", "float64", "float128",
"uint", "uint8", "uint16", "uint32", "uint64", "uint", "uint8", "uint16", "uint32", "uint64",
"opt", "sink", "owned", "sink",
"lent ", "varargs[$1]", "UncheckedArray[$1]", "Error Type", "lent", "varargs[$1]", "UncheckedArray[$1]", "Error Type",
"BuiltInTypeClass", "UserTypeClass", "BuiltInTypeClass", "UserTypeClass",
"UserTypeClassInst", "CompositeTypeClass", "inferred", "UserTypeClassInst", "CompositeTypeClass", "inferred",
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor", "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]) result = typeToStr[t.kind] % typeToString(t.sons[0])
of tySink: of tySink:
result = "sink " & typeToString(t.sons[0]) result = "sink " & typeToString(t.sons[0])
of tyOwned:
result = "owned " & typeToString(t.sons[0])
else: else:
result = typeToStr[t.kind] result = typeToStr[t.kind]
result.addTypeFlags(t) result.addTypeFlags(t)
@ -1328,7 +1331,7 @@ proc baseOfDistinct*(t: PType): PType =
result = copyType(t, t.owner, false) result = copyType(t, t.owner, false)
var parent: PType = nil var parent: PType = nil
var it = result var it = result
while it.kind in {tyPtr, tyRef}: while it.kind in {tyPtr, tyRef, tyOwned}:
parent = it parent = it
it = it.lastSon it = it.lastSon
if it.kind == tyDistinct and parent != nil: if it.kind == tyDistinct and parent != nil: