From a6d49c3a81acb453306a902b08e5bac52fe1ea47 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 3 Mar 2019 19:00:05 +0100 Subject: [PATCH] special typing rules for owned pointers --- compiler/commands.nim | 3 ++- compiler/options.nim | 3 ++- compiler/semexprs.nim | 4 ++++ compiler/semobjconstr.nim | 7 ++++-- compiler/semstmts.nim | 4 ++++ lib/system.nim | 50 +++++++++++++++++++++++++++------------ 6 files changed, 52 insertions(+), 19 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index 583d2bb9e7..404be3df3f 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -738,7 +738,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; expectNoArg(conf, switch, arg, pass, info) doAssert(conf != nil) incl(conf.features, destructor) - defineSymbol(conf.symbols, "nimNewRuntime") + incl(conf.globalOptions, optNimV2) + defineSymbol(conf.symbols, "nimV2") of "stylecheck": case arg.normalize of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError} diff --git a/compiler/options.nim b/compiler/options.nim index f3594ca113..4bb17a03f4 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -19,7 +19,7 @@ const useEffectSystem* = true useWriteTracking* = false hasFFI* = defined(nimHasLibFFI) - copyrightYear* = "2018" + copyrightYear* = "2019" type # please make sure we have under 32 options # (improves code efficiency a lot!) @@ -82,6 +82,7 @@ type # please make sure we have under 32 options optNoNimblePath optHotCodeReloading optDynlibOverrideAll + optNimV2 TGlobalOptions* = set[TGlobalOption] diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 46ae4941ac..ef5315a61a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1516,6 +1516,10 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} = n.sons[1] = takeImplicitAddr(c, ri, x.typ.kind == tyLent) x.typ.flags.incl tfVarIsPtr #echo x.info, " setting it for this type ", typeToString(x.typ), " ", n.info + # Special typing rule: do not allow to pass 'owned T' to 'T' in 'result = x': + if ri.typ != nil and ri.typ.skipTypes(abstractInst).kind == tyOwned and + le.typ != nil and le.typ.skipTypes(abstractInst).kind != tyOwned: + localError(c.config, n.info, "cannot return an owned pointer as an unowned pointer") template resultTypeIsInferrable(typ: PType): untyped = typ.isMetaType and typ.kind != tyTypeDesc diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim index 90ab2c57a3..a08e9c6352 100644 --- a/compiler/semobjconstr.nim +++ b/compiler/semobjconstr.nim @@ -263,8 +263,11 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = localError(c.config, n.info, errGenerated, "object constructor needs an object type") return - t = skipTypes(t, {tyGenericInst, tyAlias, tySink}) - if t.kind == tyRef: t = skipTypes(t.sons[0], {tyGenericInst, tyAlias, tySink}) + t = skipTypes(t, {tyGenericInst, tyAlias, tySink, tyOwned}) + if t.kind == tyRef: + t = skipTypes(t.sons[0], {tyGenericInst, tyAlias, tySink, tyOwned}) + if optNimV2 in c.config.globalOptions: + result.typ = makeVarType(c, result.typ, tyOwned) if t.kind != tyObject: localError(c.config, n.info, errGenerated, "object constructor needs an object type") return diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index c16de07233..163a858958 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -474,6 +474,10 @@ 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 else: if symkind == skLet: localError(c.config, a.info, errLetNeedsInit) diff --git a/lib/system.nim b/lib/system.nim index a066e5e69d..5df804a3af 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1341,22 +1341,42 @@ proc `is`*[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.} template `isnot`*(x, y: untyped): untyped = not (x is y) ## Negated version of `is`. Equivalent to ``not(x is y)``. -proc new*[T](a: var ref T) {.magic: "New", noSideEffect.} - ## creates a new object of type ``T`` and returns a safe (traced) - ## reference to it in ``a``. +when defined(nimV2): + type owned*[T]{.magic: "BuiltinType".} -proc new*(t: typedesc): auto = - ## creates a new object of type ``T`` and returns a safe (traced) - ## reference to it as result value. - ## - ## When ``T`` is a ref type then the resulting type will be ``T``, - ## otherwise it will be ``ref T``. - when (t is ref): - var r: t - else: - var r: ref t - new(r) - return r + proc new*[T](a: var owned(ref T)) {.magic: "New", noSideEffect.} + ## creates a new object of type ``T`` and returns a safe (traced) + ## reference to it in ``a``. + + proc new*(t: typedesc): auto = + ## creates a new object of type ``T`` and returns a safe (traced) + ## reference to it as result value. + ## + ## When ``T`` is a ref type then the resulting type will be ``T``, + ## otherwise it will be ``ref T``. + when (t is ref): + var r: owned t + else: + var r: owned(ref t) + new(r) + return r +else: + proc new*[T](a: var ref T) {.magic: "New", noSideEffect.} + ## creates a new object of type ``T`` and returns a safe (traced) + ## reference to it in ``a``. + + proc new*(t: typedesc): auto = + ## creates a new object of type ``T`` and returns a safe (traced) + ## reference to it as result value. + ## + ## When ``T`` is a ref type then the resulting type will be ``T``, + ## otherwise it will be ``ref T``. + when (t is ref): + var r: t + else: + var r: ref t + new(r) + return r proc `of`*[T, S](x: typeDesc[T], y: typeDesc[S]): bool {.magic: "Of", noSideEffect.} proc `of`*[T, S](x: T, y: typeDesc[S]): bool {.magic: "Of", noSideEffect.}