diff options
-rw-r--r-- | compiler/liftdestructors.nim | 2 | ||||
-rw-r--r-- | compiler/sempass2.nim | 7 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | tests/destructor/ttuple.nim | 48 |
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) + + |