summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/sem.nim14
-rw-r--r--tests/objects/tobject_default_value.nim74
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()