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
parent ddc86d1b4b
commit 0a84b8fb4d
7 changed files with 53 additions and 9 deletions

View File

@@ -644,7 +644,7 @@ type
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
mNewString, mNewStringOfCap, mParseBiggestFloat,
mMove, mWasMoved, mDestroy,
mDefault, mAccessEnv, mReset,
mDefault, mUnown, mAccessEnv, mReset,
mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs,
mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
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 mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($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:
if optNimV2 in p.config.globalOptions:
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 mFloatToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
of mCStrToStr: applyFormat("cstrToNimstr($1)", "cstrToNimstr($1)")
of mStrToStr: applyFormat("$1", "$1")
of mStrToStr, mUnown: applyFormat("$1", "$1")
else:
assert false, $op

View File

@@ -322,6 +322,39 @@ proc semOf(c: PContext, n: PNode): PNode =
n.typ = getSysType(c.graph, n.info, tyBool)
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,
flags: TExprFlags): PNode =
## 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)
if t.destructor != nil:
result.sons[0] = newSymNode(t.destructor)
of mUnown:
result = semUnown(c, n)
else: result = n

View File

@@ -471,10 +471,14 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
($typ.kind).substr(2).toLowerAscii)
elif typ.kind == tyProc and tfUnresolved in typ.flags:
localError(c.config, def.info, errProcHasNoConcreteType % def.renderTree)
elif 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
when false:
# XXX This typing rule is neither documented nor complete enough to
# justify it. Instead use the newer 'unowned x' until we figured out
# 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:
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.genAsgnPatch(n.sons[1], 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:
unused(c, n, dest)
c.genNew(n)

View File

@@ -1619,7 +1619,7 @@ template `isnot`*(x, y: untyped): untyped = not (x is y)
## assert @[1, 2] isnot enum
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.}
## 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)
new(r)
return r
proc unown*[T](x: T): T {.magic: "Unown", noSideEffect.}
## Use the expression ``x`` ignoring its ownership attribute.
else:
template owned*(t: typeDesc): typedesc = t
template unown*(x: typed): typed = x
proc new*[T](a: var ref T) {.magic: "New", noSideEffect.}
## Creates a new object of type ``T`` and returns a safe (traced)