parent
9c3e23e075
commit
d3db189eb4
4 changed files with 77 additions and 10 deletions
|
|
@ -325,7 +325,7 @@ proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
|
||||||
|
|
||||||
if op == nil:
|
if op == nil:
|
||||||
# give up and find the canonical type instead:
|
# give up and find the canonical type instead:
|
||||||
let h = sighashes.hashType(t, {CoType, CoConsiderOwned})
|
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
|
||||||
let canon = c.graph.canonTypes.getOrDefault(h)
|
let canon = c.graph.canonTypes.getOrDefault(h)
|
||||||
if canon != nil:
|
if canon != nil:
|
||||||
op = canon.attachedOps[kind]
|
op = canon.attachedOps[kind]
|
||||||
|
|
|
||||||
|
|
@ -593,12 +593,13 @@ proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
|
||||||
if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.skipTypes({tyAlias}).flags != {}: return
|
if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.skipTypes({tyAlias}).flags != {}: return
|
||||||
incl orig.flags, tfCheckedForDestructor
|
incl orig.flags, tfCheckedForDestructor
|
||||||
|
|
||||||
let h = sighashes.hashType(orig, {CoType, CoConsiderOwned})
|
let h = sighashes.hashType(orig, {CoType, CoConsiderOwned, CoDistinct})
|
||||||
var canon = c.graph.canonTypes.getOrDefault(h)
|
var canon = c.graph.canonTypes.getOrDefault(h)
|
||||||
var overwrite = false
|
var overwrite = false
|
||||||
if canon == nil:
|
if canon == nil:
|
||||||
c.graph.canonTypes[h] = orig
|
let typ = orig.skipTypes({tyGenericInst, tyAlias})
|
||||||
canon = orig
|
c.graph.canonTypes[h] = typ
|
||||||
|
canon = typ
|
||||||
elif canon != orig:
|
elif canon != orig:
|
||||||
overwrite = true
|
overwrite = true
|
||||||
|
|
||||||
|
|
@ -608,17 +609,17 @@ proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
|
||||||
# 3. we have a lifted destructor.
|
# 3. we have a lifted destructor.
|
||||||
# 4. We have a custom destructor.
|
# 4. We have a custom destructor.
|
||||||
# 5. We have a (custom) generic destructor.
|
# 5. We have a (custom) generic destructor.
|
||||||
let typ = canon.skipTypes({tyGenericInst, tyAlias})
|
|
||||||
# we generate the destructor first so that other operators can depend on it:
|
# we generate the destructor first so that other operators can depend on it:
|
||||||
for k in attachedDestructor..attachedSink:
|
for k in attachedDestructor..attachedSink:
|
||||||
if typ.attachedOps[k] == nil:
|
if canon.attachedOps[k] == nil:
|
||||||
discard produceSym(c, typ, k, info)
|
discard produceSym(c, canon, k, info)
|
||||||
else:
|
else:
|
||||||
inst(typ.attachedOps[k], typ)
|
inst(canon.attachedOps[k], canon)
|
||||||
|
|
||||||
if overwrite:
|
if overwrite:
|
||||||
for k in attachedDestructor..attachedSink:
|
for k in attachedDestructor..attachedSink:
|
||||||
orig.attachedOps[k] = typ.attachedOps[k]
|
orig.attachedOps[k] = canon.attachedOps[k]
|
||||||
|
|
||||||
if not isTrival(orig.destructor):
|
if not isTrival(orig.destructor):
|
||||||
#or not isTrival(orig.assignment) or
|
#or not isTrival(orig.assignment) or
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ type
|
||||||
CoOwnerSig
|
CoOwnerSig
|
||||||
CoIgnoreRange
|
CoIgnoreRange
|
||||||
CoConsiderOwned
|
CoConsiderOwned
|
||||||
|
CoDistinct
|
||||||
|
|
||||||
proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag])
|
proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag])
|
||||||
|
|
||||||
|
|
@ -97,7 +98,11 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
c.hashType t.sons[i], flags
|
c.hashType t.sons[i], flags
|
||||||
of tyDistinct:
|
of tyDistinct:
|
||||||
if {CoType, CoConsiderOwned} * flags == {CoType} or t.sym == nil:
|
if CoDistinct in flags:
|
||||||
|
if t.sym != nil: c.hashSym(t.sym)
|
||||||
|
if t.sym == nil or tfFromGeneric in t.flags:
|
||||||
|
c.hashType t.lastSon, flags
|
||||||
|
elif CoType in flags or t.sym == nil:
|
||||||
c.hashType t.lastSon, flags
|
c.hashType t.lastSon, flags
|
||||||
else:
|
else:
|
||||||
c.hashSym(t.sym)
|
c.hashSym(t.sym)
|
||||||
|
|
|
||||||
61
tests/destructor/topt.nim
Normal file
61
tests/destructor/topt.nim
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
|
||||||
|
discard """
|
||||||
|
output: '''5
|
||||||
|
vseq destroy
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
type
|
||||||
|
opt*[T] = object
|
||||||
|
case exists: bool
|
||||||
|
of true: val: T
|
||||||
|
of false: discard
|
||||||
|
|
||||||
|
proc some*[T](val: sink T): opt[T] {.inline.} =
|
||||||
|
## Returns an ``opt`` that has the value.
|
||||||
|
## nil is considered as none for reference types
|
||||||
|
result.exists = true
|
||||||
|
result.val = val
|
||||||
|
|
||||||
|
proc none*(T: typedesc): opt[T] {.inline.} =
|
||||||
|
## Returns an ``opt`` for this type that has no value.
|
||||||
|
# the default is the none type
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc none*[T]: opt[T] {.inline.} =
|
||||||
|
## Alias for ``none(T)``.
|
||||||
|
none(T)
|
||||||
|
|
||||||
|
proc unsafeGet*[T](self: opt[T]): lent T {.inline.} =
|
||||||
|
## Returns the value of a ``some``. Behavior is undefined for ``none``.
|
||||||
|
self.val
|
||||||
|
|
||||||
|
type
|
||||||
|
VSeq*[T] = object
|
||||||
|
len: int
|
||||||
|
data: ptr UncheckedArray[T]
|
||||||
|
|
||||||
|
proc `=destroy`*[T](m: var VSeq[T]) {.inline.} =
|
||||||
|
if m.data != nil:
|
||||||
|
echo "vseq destroy"
|
||||||
|
dealloc(m.data)
|
||||||
|
m.data = nil
|
||||||
|
|
||||||
|
proc `=`*[T](m: var VSeq[T], m2: VSeq[T]) {.error.}
|
||||||
|
|
||||||
|
proc `=sink`*[T](m: var VSeq[T], m2: VSeq[T]) {.inline.} =
|
||||||
|
if m.data != m2.data:
|
||||||
|
`=destroy`(m)
|
||||||
|
m.len = m2.len
|
||||||
|
m.data = m2.data
|
||||||
|
|
||||||
|
proc newVSeq*[T](len: int): VSeq[T] =
|
||||||
|
## Only support sequence creation from scalar size because creation from
|
||||||
|
## vetorized size can't reproduce the original scalar size
|
||||||
|
result.len = len
|
||||||
|
if len > 0:
|
||||||
|
result.data = cast[ptr UncheckedArray[T]](alloc(sizeof(T) * len))
|
||||||
|
|
||||||
|
let x = some newVSeq[float](5)
|
||||||
|
echo x.unsafeGet.len
|
||||||
|
let y = none(VSeq[float])
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue