This commit is contained in:
Andreas Rumpf 2020-07-27 23:27:20 +02:00 • committed by GitHub
commit e6f0d4a5a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 28 deletions

View file

@ -48,6 +48,13 @@ type
const toDebug {.strdefine.} = ""
proc hasDestructor(c: Con; t: PType): bool {.inline.} =
result = ast.hasDestructor(t)
when toDebug.len > 0:
# for more effective debugging
if not result and c.graph.config.selectedGC in {gcArc, gcOrc}:
assert(not containsGarbageCollectedRef(t))
template dbg(body) =
when toDebug.len > 0:
if c.owner.name.s == toDebug or toDebug == "always":
@ -330,7 +337,7 @@ proc genDiscriminantAsgn(c: var Con; s: var Scope; n: PNode): PNode =
let leDotExpr = if le.kind == nkCheckedFieldExpr: le[0] else: le
let objType = leDotExpr[0].typ
if hasDestructor(objType):
if hasDestructor(c, objType):
if objType.attachedOps[attachedDestructor] != nil and
sfOverriden in objType.attachedOps[attachedDestructor].flags:
localError(c.graph.config, n.info, errGenerated, """Assignment to discriminant for objects with user defined destructor is not supported, object must have default destructor.
@ -364,8 +371,8 @@ proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
# generate: (let tmp = v; reset(v); tmp)
if not hasDestructor(n.typ):
assert n.kind != nkSym or not hasDestructor(n.sym.typ)
if not hasDestructor(c, n.typ):
assert n.kind != nkSym or not hasDestructor(c, n.sym.typ)
result = copyTree(n)
else:
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
@ -393,7 +400,7 @@ proc isCapturedVar(n: PNode): bool =
proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
let tmp = c.getTemp(s, n.typ, n.info)
if hasDestructor(n.typ):
if hasDestructor(c, n.typ):
result.add c.genWasMoved(tmp)
var m = c.genCopy(tmp, n)
m.add p(n, c, s, normal)
@ -432,7 +439,7 @@ proc containsConstSeq(n: PNode): bool =
proc ensureDestruction(arg, orig: PNode; c: var Con; s: var Scope): PNode =
# it can happen that we need to destroy expression contructors
# like [], (), closures explicitly in order to not leak them.
if arg.typ != nil and hasDestructor(arg.typ):
if arg.typ != nil and hasDestructor(c, arg.typ):
# produce temp creation for (fn, env). But we need to move 'env'?
# This was already done in the sink parameter handling logic.
result = newNodeIT(nkStmtListExpr, arg.info, arg.typ)
@ -521,7 +528,7 @@ template processScopeExpr(c: var Con; s: var Scope; ret: PNode, processCall: unt
# tricky because you would have to intercept moveOrCopy at a certain point
let tmp = c.getTemp(s.parent[], ret.typ, ret.info)
tmp.sym.flags.incl sfSingleUsedTemp
let cpy = if ret.typ.hasDestructor:
let cpy = if hasDestructor(c, ret.typ):
moveOrCopy(tmp, ret, c, s, isDecl = true)
else:
newTree(nkFastAsgn, tmp, p(ret, c, s, normal))
@ -774,10 +781,10 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
result = newNodeI(nkStmtList, n.info)
for it in n:
var ri = it[^1]
if it.kind == nkVarTuple and hasDestructor(ri.typ):
if it.kind == nkVarTuple and hasDestructor(c, ri.typ):
let x = lowerTupleUnpacking(c.graph, it, c.owner)
result.add p(x, c, s, consumed)
elif it.kind == nkIdentDefs and hasDestructor(it[0].typ) and not isCursor(it[0], c):
elif it.kind == nkIdentDefs and hasDestructor(c, it[0].typ) and not isCursor(it[0], c):
for j in 0..<it.len-2:
let v = it[j]
if v.kind == nkSym:
@ -797,7 +804,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
v.add itCopy
result.add v
of nkAsgn, nkFastAsgn:
if hasDestructor(n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda} and
if hasDestructor(c, n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda} and
not isCursor(n[0], c):
# rule (self-assignment-removal):
if n[1].kind == nkSym and n[0].kind == nkSym and n[0].sym == n[1].sym:
@ -828,7 +835,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
result = shallowCopy(n)
for i in 0 ..< n.len:
result[i] = p(n[i], c, s, normal)
if n.typ != nil and hasDestructor(n.typ):
if n.typ != nil and hasDestructor(c, n.typ):
if mode == normal:
result = ensureDestruction(result, n, c, s)
@ -858,7 +865,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
result[0] = p(n[0], c, s, normal)
for i in 1 ..< n.len:
result[i] = n[i]
if mode == sinkArg and hasDestructor(n.typ):
if mode == sinkArg and hasDestructor(c, n.typ):
if isAnalysableFieldAccess(n, c.owner) and isLastRead(n, c):
s.wasMoved.add c.genWasMoved(n)
else:
@ -868,7 +875,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
result = shallowCopy(n)
for i in 0 ..< n.len:
result[i] = p(n[i], c, s, normal)
if mode == sinkArg and hasDestructor(n.typ):
if mode == sinkArg and hasDestructor(c, n.typ):
if isAnalysableFieldAccess(n, c.owner) and isLastRead(n, c):
# consider 'a[(g; destroy(g); 3)]', we want to say 'wasMoved(a[3])'
# without the junk, hence 'c.genWasMoved(n)'
@ -1004,7 +1011,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
let params = owner.typ.n
for i in 1..<params.len:
let t = params[i].sym.typ
if isSinkTypeForParam(t) and hasDestructor(t.skipTypes({tySink})):
if isSinkTypeForParam(t) and hasDestructor(c, t.skipTypes({tySink})):
scope.final.add c.genDestroy(params[i])
#if optNimV2 in c.graph.config.globalOptions:
# injectDefaultCalls(n, c)