diff options
-rw-r--r-- | compiler/sem.nim | 14 | ||||
-rw-r--r-- | tests/objects/tobject_default_value.nim | 74 |
2 files changed, 81 insertions, 7 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim index bac029fb9..3b20579d5 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -578,14 +578,14 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): s result.add newTree(nkExprColonExpr, recNode, asgnExpr) return - let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), recType.owner) - rawAddSon(asgnType, recType) + let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), recNode.typ.owner) + rawAddSon(asgnType, recNode.typ) let asgnExpr = newTree(nkCall, newSymNode(getSysMagic(c.graph, recNode.info, "zeroDefault", mZeroDefault)), newNodeIT(nkType, recNode.info, asgnType) ) asgnExpr.flags.incl nfSkipFieldChecking - asgnExpr.typ = recType + asgnExpr.typ = recNode.typ result.add newTree(nkExprColonExpr, recNode, asgnExpr) else: doAssert false @@ -615,9 +615,9 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] = if field.ast != nil: #Try to use default value result.add newTree(nkExprColonExpr, recNode, field.ast) elif recType.kind in {tyObject, tyArray, tyTuple}: - let asgnExpr = defaultNodeField(c, recNode, recType) + let asgnExpr = defaultNodeField(c, recNode, recNode.typ) if asgnExpr != nil: - asgnExpr.typ = recType + asgnExpr.typ = recNode.typ asgnExpr.flags.incl nfSkipFieldChecking result.add newTree(nkExprColonExpr, recNode, asgnExpr) else: @@ -628,8 +628,8 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode = if aTypSkip.kind == tyObject: let child = defaultFieldsForTheUninitialized(c, aTypSkip.n) if child.len > 0: - var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTypSkip)) - asgnExpr.typ = aTypSkip + var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTyp)) + asgnExpr.typ = aTyp asgnExpr.sons.add child result = semExpr(c, asgnExpr) elif aTypSkip.kind == tyArray: diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 97e3a207d..b571965ea 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -614,6 +614,80 @@ template main {.dirty.} = type SearchOptions = object evaluation = evaluate + block: + type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate: bool + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + discard + else: + when E is void: + case oResultPrivate: bool + of false: + discard + of true: + vResultPrivate: T + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + vResultPrivate: T + + + template `?`[T, E](self: Result[T, E]): auto = + let v = (self) + if not v.oResultPrivate: + when compiles(`assignResult?`(default(typeof(result)))): + when typeof(result) is typeof(v): + `assignResult?`(v) + elif E is void: + `assignResult?`(err(typeof(result))) + else: + `assignResult?`(err(typeof(result), v.eResultPrivate)) + return + else: + return + when typeof(result) is typeof(v): + v + elif E is void: + err(typeof(result)) + else: + err(typeof(result), v.eResultPrivate) + + when not(T is void): + v.vResultPrivate + + type R = Result[int, string] + + proc testAssignResult() = + var assigned: bool + template `assignResult?`(v: Result) = + assigned = true + result = v + + proc failed(): Result[int, string] = + discard + + proc calling(): Result[int, string] = + let _ = ? failed() + doAssert false + + let r = calling() + doAssert assigned + + when nimvm: + when not defined(js): + testAssignResult() + else: + testAssignResult() + static: main() main() |