added system.unown to make 'owned' sane to use in practice; later on we might change the type inference rules to make it more convenient

This commit is contained in:
Araq 2019-04-29 13:35:30 +02:00
commit 0a84b8fb4d
7 changed files with 53 additions and 9 deletions

View file

@ -644,7 +644,7 @@ type
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
mNewString, mNewStringOfCap, mParseBiggestFloat, mNewString, mNewStringOfCap, mParseBiggestFloat,
mMove, mWasMoved, mDestroy, mMove, mWasMoved, mDestroy,
mDefault, mAccessEnv, mReset, mDefault, mUnown, mAccessEnv, mReset,
mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs, mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs,
mRef, mPtr, mVar, mDistinct, mVoid, mTuple, mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
mOrdinal, mOrdinal,

View file

@ -2179,7 +2179,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)") of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)")
of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)") of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)")
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)") of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
of mStrToStr: expr(p, e.sons[1], d) of mStrToStr, mUnown: expr(p, e.sons[1], d)
of mEnumToStr: of mEnumToStr:
if optNimV2 in p.config.globalOptions: if optNimV2 in p.config.globalOptions:
genEnumToStr(p, e, d) genEnumToStr(p, e, d)

View file

@ -640,7 +640,7 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mInt64ToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")") of mInt64ToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
of mFloatToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")") of mFloatToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
of mCStrToStr: applyFormat("cstrToNimstr($1)", "cstrToNimstr($1)") of mCStrToStr: applyFormat("cstrToNimstr($1)", "cstrToNimstr($1)")
of mStrToStr: applyFormat("$1", "$1") of mStrToStr, mUnown: applyFormat("$1", "$1")
else: else:
assert false, $op assert false, $op

View file

@ -322,6 +322,39 @@ proc semOf(c: PContext, n: PNode): PNode =
n.typ = getSysType(c.graph, n.info, tyBool) n.typ = getSysType(c.graph, n.info, tyBool)
result = n result = n
proc semUnown(c: PContext; n: PNode): PNode =
proc unownedType(c: PContext; t: PType): PType =
case t.kind
of tyTuple:
var elems = newSeq[PType](t.len)
var someChange = false
for i in 0..<t.len:
elems[i] = unownedType(c, t[i])
if elems[i] != t[i]: someChange = true
if someChange:
result = newType(tyTuple, t.owner)
# we have to use 'rawAddSon' here so that type flags are
# properly computed:
for e in elems: result.rawAddSon(e)
else:
result = t
of tyOwned: result = t.sons[0]
of tySequence, tyOpenArray, tyArray, tyVarargs, tyVar, tyLent,
tyGenericInst, tyAlias:
let L = t.len-1
let b = unownedType(c, t[L])
if b != t[L]:
result = copyType(t, t.owner, keepId = false)
result[L] = b
result.flags.excl tfHasOwned
else:
result = t
else:
result = t
result = copyTree(n[1])
result.typ = unownedType(c, result.typ)
proc magicsAfterOverloadResolution(c: PContext, n: PNode, proc magicsAfterOverloadResolution(c: PContext, n: PNode,
flags: TExprFlags): PNode = flags: TExprFlags): PNode =
## This is the preferred code point to implement magics. ## This is the preferred code point to implement magics.
@ -433,4 +466,6 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
let t = n[1].typ.skipTypes(abstractVar) let t = n[1].typ.skipTypes(abstractVar)
if t.destructor != nil: if t.destructor != nil:
result.sons[0] = newSymNode(t.destructor) result.sons[0] = newSymNode(t.destructor)
of mUnown:
result = semUnown(c, n)
else: result = n else: result = n

View file

@ -471,10 +471,14 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
($typ.kind).substr(2).toLowerAscii) ($typ.kind).substr(2).toLowerAscii)
elif typ.kind == tyProc and tfUnresolved in typ.flags: elif typ.kind == tyProc and tfUnresolved in typ.flags:
localError(c.config, def.info, errProcHasNoConcreteType % def.renderTree) localError(c.config, def.info, errProcHasNoConcreteType % def.renderTree)
elif symkind == skVar and typ.kind == tyOwned and def.kind notin nkCallKinds: when false:
# special type inference rule: 'var it = ownedPointer' is turned # XXX This typing rule is neither documented nor complete enough to
# into an unowned pointer. # justify it. Instead use the newer 'unowned x' until we figured out
typ = typ.lastSon # a more general solution.
if symkind == skVar and typ.kind == tyOwned and def.kind notin nkCallKinds:
# special type inference rule: 'var it = ownedPointer' is turned
# into an unowned pointer.
typ = typ.lastSon
else: else:
if symkind == skLet: localError(c.config, a.info, errLetNeedsInit) if symkind == skLet: localError(c.config, a.info, errLetNeedsInit)

View file

@ -957,7 +957,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.genNarrow(n.sons[1], d) c.genNarrow(n.sons[1], d)
c.genAsgnPatch(n.sons[1], d) c.genAsgnPatch(n.sons[1], d)
c.freeTemp(d) c.freeTemp(d)
of mOrd, mChr, mArrToSeq: c.gen(n.sons[1], dest) of mOrd, mChr, mArrToSeq, mUnown: c.gen(n.sons[1], dest)
of mNew, mNewFinalize: of mNew, mNewFinalize:
unused(c, n, dest) unused(c, n, dest)
c.genNew(n) c.genNew(n)

View file

@ -1619,7 +1619,7 @@ template `isnot`*(x, y: untyped): untyped = not (x is y)
## assert @[1, 2] isnot enum ## assert @[1, 2] isnot enum
when defined(nimV2) and not defined(nimscript): when defined(nimV2) and not defined(nimscript):
type owned*{.magic: "BuiltinType".}[T] type owned*{.magic: "BuiltinType".}[T] ## type constructor to mark a ref/ptr or a closure as `owned`.
proc new*[T](a: var owned(ref T)) {.magic: "New", noSideEffect.} proc new*[T](a: var owned(ref T)) {.magic: "New", noSideEffect.}
## Creates a new object of type ``T`` and returns a safe (traced) ## Creates a new object of type ``T`` and returns a safe (traced)
@ -1637,8 +1637,13 @@ when defined(nimV2) and not defined(nimscript):
var r: owned(ref t) var r: owned(ref t)
new(r) new(r)
return r return r
proc unown*[T](x: T): T {.magic: "Unown", noSideEffect.}
## Use the expression ``x`` ignoring its ownership attribute.
else: else:
template owned*(t: typeDesc): typedesc = t template owned*(t: typeDesc): typedesc = t
template unown*(x: typed): typed = x
proc new*[T](a: var ref T) {.magic: "New", noSideEffect.} proc new*[T](a: var ref T) {.magic: "New", noSideEffect.}
## Creates a new object of type ``T`` and returns a safe (traced) ## Creates a new object of type ``T`` and returns a safe (traced)