summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/liftdestructors.nim2
-rw-r--r--compiler/sempass2.nim7
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--tests/destructor/ttuple.nim48
4 files changed, 56 insertions, 3 deletions
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim
index 8ea28fea0..1cac61094 100644
--- a/compiler/liftdestructors.nim
+++ b/compiler/liftdestructors.nim
@@ -610,7 +610,7 @@ proc createTypeBoundOps*(c: PContext; orig: PType; info: TLineInfo) =
   ## In the semantic pass this is called in strategic places
   ## to ensure we lift assignment, destructors and moves properly.
   ## The later 'injectdestructors' pass depends on it.
-  if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.flags != {}: return
+  if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.skipTypes({tyAlias}).flags != {}: return
   incl orig.flags, tfCheckedForDestructor
 
   let h = sighashes.hashType(orig, {CoType, CoConsiderOwned})
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index cab79314a..a07053643 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -776,7 +776,12 @@ proc track(tracked: PEffects, n: PNode) =
       let last = lastSon(child)
       if last.kind != nkEmpty: track(tracked, last)
       if tracked.owner.kind != skMacro:
-        createTypeBoundOps(tracked.c, child[0].typ, child.info)
+        if child.kind == nkVarTuple:
+          createTypeBoundOps(tracked.c, child[^1].typ, child.info)
+          for i in 0..child.len-3:
+            createTypeBoundOps(tracked.c, child[i].typ, child.info)
+        else:
+          createTypeBoundOps(tracked.c, child[0].typ, child.info)
       if child.kind == nkIdentDefs and last.kind != nkEmpty:
         for i in 0 .. child.len-3:
           initVar(tracked, child.sons[i], volatileCheck=false)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index a3df95190..6fd87d26f 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -2120,7 +2120,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
             continue
 
         let verdict = semConstExpr(c, n[i])
-        if verdict.intVal == 0:
+        if verdict == nil or verdict.kind != nkIntLit or verdict.intVal == 0:
           localError(c.config, result.info, "concept predicate failed")
       of tyUnknown: continue
       else: discard
diff --git a/tests/destructor/ttuple.nim b/tests/destructor/ttuple.nim
new file mode 100644
index 000000000..ec12dfc3a
--- /dev/null
+++ b/tests/destructor/ttuple.nim
@@ -0,0 +1,48 @@
+
+discard """
+   output: '''5.0 10.0'''
+"""
+
+type
+  MyOpt[T] = object
+    case has: bool:
+      of true: val: T
+      of false: nil
+
+  MyVal = object
+    f: ptr float
+
+proc `=destroy`(x: var MyVal) =
+  if x.f != nil:
+    dealloc(x.f)
+
+proc `=sink`(x1: var MyVal, x2: Myval) =
+  if x1.f != x2.f:
+    `=destroy`(x1)
+    x1.f = x2.f
+
+proc `=`(x1: var MyVal, x2: Myval) =
+  if x1.f != x2.f:
+    `=destroy`(x1)
+    x1.f = create(float)
+    x1.f[] = x2.f[]
+
+proc newVal(x: float): MyVal =
+  result.f = create(float)
+  result.f[] = x
+
+template getIt[T, R](self: MyOpt[T], body: untyped, default: R): R =
+  if self.has:
+    template it: untyped {.inject.} = self.val
+    body
+  else:
+    default
+
+proc myproc(h: MyOpt[float]) =
+  let (a, b) = h.getIt((newVal(it), newVal(it * 2)), (newVal(1.0), newVal(1.0)))
+  echo a.f[], " ", b.f[]
+
+let h = MyOpt[float](has: true, val: 5.0)
+myproc(h)
+
+