diff options
-rw-r--r-- | changelog.md | 2 | ||||
-rw-r--r-- | compiler/semobjconstr.nim | 21 | ||||
-rw-r--r-- | compiler/semstmts.nim | 3 | ||||
-rw-r--r-- | compiler/typeallowed.nim | 3 | ||||
-rw-r--r-- | doc/manual.rst | 30 | ||||
-rw-r--r-- | tests/distinct/tdistinct.nim | 32 |
6 files changed, 82 insertions, 9 deletions
diff --git a/changelog.md b/changelog.md index 871fb229d..53730ecc5 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,8 @@ ## Standard library additions and changes +- Make `{.requiresInit.}` pragma to work for `distinct` types. + - `prelude` now works with the JavaScript target. - Added `ioutils` module containing `duplicate` and `duplicateTo` to duplicate `FileHandle` using C function `dup` and `dup2`. diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim index 64a27d1db..42529e1e5 100644 --- a/compiler/semobjconstr.nim +++ b/compiler/semobjconstr.nim @@ -355,15 +355,22 @@ proc computeRequiresInit(c: PContext, t: PType): bool = proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) = var objType = t - while objType.kind != tyObject: + while objType.kind notin {tyObject, tyDistinct}: objType = objType.lastSon assert objType != nil - var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info)) - let initResult = semConstructTypeAux(c, constrCtx, {}) - assert constrCtx.missingFields.len > 0 - localError(c.config, info, - "The $1 type doesn't have a default value. The following fields must be initialized: $2.", - [typeToString(t), listSymbolNames(constrCtx.missingFields)]) + if objType.kind == tyObject: + var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info)) + let initResult = semConstructTypeAux(c, constrCtx, {}) + assert constrCtx.missingFields.len > 0 + localError(c.config, info, + "The $1 type doesn't have a default value. The following fields must " & + "be initialized: $2.", + [typeToString(t), listSymbolNames(constrCtx.missingFields)]) + elif objType.kind == tyDistinct: + localError(c.config, info, + "The $1 distinct type doesn't have a default value.", [typeToString(t)]) + else: + assert false, "Must not enter here." proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = var t = semTypeNode(c, n[0], nil) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 2a058eee2..4b79cd546 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -611,7 +611,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = if def.kind == nkEmpty: let actualType = v.typ.skipTypes({tyGenericInst, tyAlias, tyUserTypeClassInst}) - if actualType.kind == tyObject and actualType.requiresInit: + if actualType.kind in {tyObject, tyDistinct} and + actualType.requiresInit: defaultConstructionError(c, v.typ, v.info) else: checkNilable(c, v) diff --git a/compiler/typeallowed.nim b/compiler/typeallowed.nim index a8210508c..e163b914a 100644 --- a/compiler/typeallowed.nim +++ b/compiler/typeallowed.nim @@ -260,4 +260,5 @@ proc directViewType*(t: PType): ViewTypeKind = result = noView proc requiresInit*(t: PType): bool = - (t.flags * {tfRequiresInit, tfNotNil} != {}) or classifyViewType(t) != noView + (t.flags * {tfRequiresInit, tfNeedsFullInit, tfNotNil} != {}) or + classifyViewType(t) != noView diff --git a/doc/manual.rst b/doc/manual.rst index d9f9cc9b9..4e5b861b1 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -2697,6 +2697,36 @@ the variable has been initialized and does not rely on syntactic properties: x = a() # use x +`requiresInit` pragma can also be applyied to `distinct` types. + +Given the following distinct type definitions: + +.. code-block:: nim + type + DistinctObject {.requiresInit, borrow: `.`.} = distinct MyObject + DistinctString {.requiresInit.} = distinct string + +The following code blocks will fail to compile: + +.. code-block:: nim + var foo: DistinctFoo + foo.x = "test" + doAssert foo.x == "test" + +.. code-block:: nim + var s: DistinctString + s = "test" + doAssert s == "test" + +But these ones will compile successfully: + +.. code-block:: nim + let foo = DistinctFoo(Foo(x: "test")) + doAssert foo.x == "test" + +.. code-block:: nim + let s = "test" + doAssert s == "test" Let statement ------------- diff --git a/tests/distinct/tdistinct.nim b/tests/distinct/tdistinct.nim index 2c0196745..d64f33443 100644 --- a/tests/distinct/tdistinct.nim +++ b/tests/distinct/tdistinct.nim @@ -106,3 +106,35 @@ type FooD = distinct int proc `<=`(a, b: FooD): bool {.borrow.} for f in [FooD(0): "Foo"]: echo f + +block tRequiresInit: + template accept(x) = + static: doAssert compiles(x) + + template reject(x) = + static: doAssert not compiles(x) + + type + Foo = object + x: string + + DistinctFoo {.requiresInit, borrow: `.`.} = distinct Foo + DistinctString {.requiresInit.} = distinct string + + reject: + var foo: DistinctFoo + foo.x = "test" + doAssert foo.x == "test" + + accept: + let foo = DistinctFoo(Foo(x: "test")) + doAssert foo.x == "test" + + reject: + var s: DistinctString + s = "test" + doAssert s == "test" + + accept: + let s = "test" + doAssert s == "test" |