mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 10:22:15 +00:00
destructors: lift type bound operations for case and distinct objects (#10238)
This commit is contained in:
@@ -49,6 +49,14 @@ proc liftBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
|
||||
liftBodyAux(c, f.typ, body, x.dotField(f), y.dotField(f))
|
||||
of nkNilLit: discard
|
||||
of nkRecCase:
|
||||
if c.kind in {attachedSink, attachedAsgn, attachedDeepCopy}:
|
||||
## the value needs to be destroyed before we assign the selector
|
||||
## or the value is lost
|
||||
let prevKind = c.kind
|
||||
c.kind = attachedDestructor
|
||||
liftBodyObj(c, n, body, x, y)
|
||||
c.kind = prevKind
|
||||
|
||||
# copy the selector:
|
||||
liftBodyObj(c, n[0], body, x, y)
|
||||
# we need to generate a case statement:
|
||||
@@ -66,7 +74,6 @@ proc liftBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
|
||||
liftBodyObj(c, n[i].lastSon, branch.sons[L-1], x, y)
|
||||
caseStmt.add(branch)
|
||||
body.add(caseStmt)
|
||||
localError(c.c.config, c.info, "cannot lift assignment operator to 'case' object")
|
||||
of nkRecList:
|
||||
for t in items(n): liftBodyObj(c, t, body, x, y)
|
||||
else:
|
||||
@@ -235,11 +242,12 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
discard considerOverloadedOp(c, t, body, x, y)
|
||||
else:
|
||||
defaultOp(c, t, body, x, y)
|
||||
of tyObject, tyDistinct:
|
||||
of tyObject:
|
||||
if not considerOverloadedOp(c, t, body, x, y):
|
||||
if t.sons[0] != nil:
|
||||
liftBodyAux(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
|
||||
if t.kind == tyObject: liftBodyObj(c, t.n, body, x, y)
|
||||
liftBodyObj(c, t.n, body, x, y)
|
||||
of tyDistinct:
|
||||
if not considerOverloadedOp(c, t, body, x, y):
|
||||
liftBodyAux(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
|
||||
of tyTuple:
|
||||
liftBodyTup(c, t, body, x, y)
|
||||
of tyProc:
|
||||
@@ -279,8 +287,36 @@ proc addParam(procType: PType; param: PSym) =
|
||||
addSon(procType.n, newSymNode(param))
|
||||
rawAddSon(procType, param.typ)
|
||||
|
||||
proc liftBodyDistinctType(c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
||||
assert typ.kind == tyDistinct
|
||||
let baseType = typ[0]
|
||||
case kind
|
||||
of attachedAsgn:
|
||||
if baseType.assignment == nil:
|
||||
discard liftBody(c, baseType, kind, info)
|
||||
typ.assignment = baseType.assignment
|
||||
result = typ.assignment
|
||||
of attachedSink:
|
||||
if baseType.sink == nil:
|
||||
discard liftBody(c, baseType, kind, info)
|
||||
typ.sink = baseType.sink
|
||||
result = typ.sink
|
||||
of attachedDeepCopy:
|
||||
if baseType.deepCopy == nil:
|
||||
discard liftBody(c, baseType, kind, info)
|
||||
typ.deepCopy = baseType.deepCopy
|
||||
result = typ.deepCopy
|
||||
of attachedDestructor:
|
||||
if baseType.destructor == nil:
|
||||
discard liftBody(c, baseType, kind, info)
|
||||
typ.destructor = baseType.destructor
|
||||
result = typ.destructor
|
||||
|
||||
proc liftBody(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
info: TLineInfo): PSym =
|
||||
if typ.kind == tyDistinct:
|
||||
return liftBodyDistinctType(c, typ, kind, info)
|
||||
|
||||
var a: TLiftCtx
|
||||
a.info = info
|
||||
a.c = c
|
||||
|
||||
@@ -7,21 +7,28 @@ mygeneric1 constructed
|
||||
mygeneric1 destroyed
|
||||
----
|
||||
mygeneric2 constructed
|
||||
mygeneric2 destroyed
|
||||
myobj destroyed
|
||||
mygeneric2 destroyed
|
||||
----
|
||||
mygeneric3 constructed
|
||||
mygeneric1 destroyed
|
||||
----
|
||||
mygeneric1 destroyed
|
||||
mydistinctObj constructed
|
||||
myobj destroyed
|
||||
mygeneric2 destroyed
|
||||
------------------
|
||||
----
|
||||
----
|
||||
myobj destroyed
|
||||
----
|
||||
----
|
||||
mygeneric1 destroyed
|
||||
myobj destroyed
|
||||
myobj destroyed
|
||||
myobj destroyed
|
||||
---
|
||||
myobj destroyed
|
||||
myobj destroyed
|
||||
myobj destroyed
|
||||
'''
|
||||
cmd: '''nim c --newruntime $file'''
|
||||
disabled: "true"
|
||||
"""
|
||||
|
||||
type
|
||||
@@ -29,6 +36,11 @@ type
|
||||
x, y: int
|
||||
p: pointer
|
||||
|
||||
proc `=destroy`(o: var TMyObj) =
|
||||
if o.p != nil: dealloc o.p
|
||||
echo "myobj destroyed"
|
||||
|
||||
type
|
||||
TMyGeneric1[T] = object
|
||||
x: T
|
||||
|
||||
@@ -36,37 +48,40 @@ type
|
||||
x: A
|
||||
y: B
|
||||
|
||||
proc `=destroy`(o: var TMyGeneric1[int]) =
|
||||
echo "mygeneric1 destroyed"
|
||||
|
||||
proc `=destroy`[A, B](o: var TMyGeneric2[A, B]) =
|
||||
echo "mygeneric2 destroyed"
|
||||
|
||||
type
|
||||
TMyGeneric3[A, B, C] = object
|
||||
x: A
|
||||
y: B
|
||||
z: C
|
||||
|
||||
TObjKind = enum A, B, C, D
|
||||
TDistinctObjX = distinct TMyGeneric3[TMyObj, TMyGeneric2[int, int], int]
|
||||
TDistinctObj = TDistinctObjX
|
||||
|
||||
TObjKind = enum Z, A, B, C, D
|
||||
|
||||
TCaseObj = object
|
||||
z: TMyGeneric3[TMyObj, float, int]
|
||||
case kind: TObjKind
|
||||
of Z: discard
|
||||
of A:
|
||||
x: TMyGeneric1[int]
|
||||
of B, C:
|
||||
y: TMyObj
|
||||
else:
|
||||
case innerKind: TObjKind
|
||||
of Z: discard
|
||||
of A, B, C:
|
||||
p: TMyGeneric3[int, float, string]
|
||||
of D:
|
||||
q: TMyGeneric3[TMyObj, int, int]
|
||||
r: string
|
||||
|
||||
proc `=destroy`(o: var TMyObj) =
|
||||
if o.p != nil: dealloc o.p
|
||||
echo "myobj destroyed"
|
||||
|
||||
proc `=destroy`(o: var TMyGeneric1[int]) =
|
||||
echo "mygeneric1 destroyed"
|
||||
|
||||
proc `=destroy`[A, B](o: var TMyGeneric2[A, B]) =
|
||||
echo "mygeneric2 destroyed"
|
||||
|
||||
proc open: TMyObj =
|
||||
# allow for superfluous ()
|
||||
result = (TMyObj(x: 1, y: 2, p: alloc(3)))
|
||||
@@ -95,6 +110,12 @@ proc mygeneric3 =
|
||||
|
||||
echo "mygeneric3 constructed"
|
||||
|
||||
proc mydistinctObj =
|
||||
var x = TMyGeneric3[TMyObj, TMyGeneric2[int, int], int](
|
||||
x: open(), y: TMyGeneric2[int, int](x: 5, y: 15), z: 20)
|
||||
|
||||
echo "mydistinctObj constructed"
|
||||
|
||||
echo "----"
|
||||
myobj()
|
||||
|
||||
@@ -107,9 +128,11 @@ mygeneric2[int](10)
|
||||
echo "----"
|
||||
mygeneric3()
|
||||
|
||||
echo "----"
|
||||
mydistinctObj()
|
||||
|
||||
proc caseobj =
|
||||
block:
|
||||
echo "----"
|
||||
var o1 = TCaseObj(kind: A, x: TMyGeneric1[int](x: 10))
|
||||
|
||||
block:
|
||||
@@ -121,10 +144,16 @@ proc caseobj =
|
||||
var o3 = TCaseObj(kind: D, innerKind: B, r: "test",
|
||||
p: TMyGeneric3[int, float, string](x: 10, y: 1.0, z: "test"))
|
||||
|
||||
block:
|
||||
echo "----"
|
||||
var o4 = TCaseObj(kind: D, innerKind: D, r: "test",
|
||||
q: TMyGeneric3[TMyObj, int, int](x: open(), y: 1, z: 0))
|
||||
|
||||
echo "------------------"
|
||||
caseobj()
|
||||
|
||||
proc caseobj_test_sink: TCaseObj =
|
||||
# check that lifted sink can destroy case val correctly
|
||||
result = TCaseObj(kind: D, innerKind: D, r: "test",
|
||||
q: TMyGeneric3[TMyObj, int, int](x: open(), y: 1, z: 0))
|
||||
result = TCaseObj(kind: B, y: open())
|
||||
|
||||
|
||||
echo "---"
|
||||
discard caseobj_test_sink()
|
||||
Reference in New Issue
Block a user