diff options
author | Araq <rumpf_a@web.de> | 2017-10-17 12:46:49 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2017-10-17 12:46:49 +0200 |
commit | 45d74f408151f21f1593bfc04bd29ea7509ddae9 (patch) | |
tree | 3fa1400ea556c6295977d25f87b3f25643ce5b12 /compiler | |
parent | 7ee825a6e5979a23cb0e0323f8d8069edc3285ba (diff) | |
download | Nim-45d74f408151f21f1593bfc04bd29ea7509ddae9.tar.gz |
destructors: preparations for upcoming changes
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 2 | ||||
-rw-r--r-- | compiler/destroyer.nim | 3 | ||||
-rw-r--r-- | compiler/semasgn.nim | 12 | ||||
-rw-r--r-- | compiler/semdata.nim | 1 | ||||
-rw-r--r-- | compiler/semexprs.nim | 3 | ||||
-rw-r--r-- | compiler/semstmts.nim | 1 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 6 |
7 files changed, 20 insertions, 8 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 6519b698a..cdc78be74 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1663,3 +1663,5 @@ when false: if n.isNil: return true for i in 0 ..< n.safeLen: if n[i].containsNil: return true + +template hasDestructor*(t: PType): bool = tfHasAsgn in t.flags diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index afa2e5e50..f97c44861 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -95,8 +95,6 @@ import intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, strutils, options, dfa, lowerings -template hasDestructor(t: PType): bool = tfHasAsgn in t.flags - const InterestingSyms = {skVar, skResult, skLet} @@ -253,6 +251,7 @@ proc p(n: PNode; c: var Con): PNode = result = copyNode(n) recurse(n, result) of nkAsgn, nkFastAsgn: + # XXX if special, call special operator if n[0].kind == nkSym and interestingSym(n[0].sym): result = moveOrCopy(n[0], n[1], c) else: diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim index caed11341..27626a1d0 100644 --- a/compiler/semasgn.nim +++ b/compiler/semasgn.nim @@ -109,7 +109,7 @@ proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = styleCheckUse(c.info, op) body.add newOpCall(op, x) result = true - of attachedAsgn: + of attachedAsgn, attachedSink: if tfHasAsgn in t.flags: var op: PSym if sameType(t, c.asgnForType): @@ -285,3 +285,13 @@ proc getAsgnOrLiftBody(c: PContext; typ: PType; info: TLineInfo): PSym = proc overloadedAsgn(c: PContext; dest, src: PNode): PNode = let a = getAsgnOrLiftBody(c, dest.typ, dest.info) result = newAsgnCall(c, a, dest, src) + +proc liftTypeBoundOps*(c: PContext; typ: PType) = + ## In the semantic pass this is called in strategic places + ## to ensure we lift assignment, destructors and moves properly. + ## Since this is done in the sem* routines generics already have + ## been resolved for us and do not complicate the logic any further. + ## We have to ensure that the 'tfHasDesctructor' flags bubbles up + ## in the generic instantiations though. + ## The later 'destroyer' pass depends on it. + if not newDestructors or not hasDestructor(typ): return diff --git a/compiler/semdata.nim b/compiler/semdata.nim index a3f0f715b..8b5803a7f 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -70,6 +70,7 @@ type TTypeAttachedOp* = enum attachedAsgn, + attachedSink, attachedDeepCopy, attachedDestructor diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 180754168..465b09814 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -670,6 +670,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode = analyseIfAddressTakenInCall(c, result) if callee.magic != mNone: result = magicsAfterOverloadResolution(c, result, flags) + if result.typ != nil: liftTypeBoundOps(c, result.typ) if c.matchedConcept == nil: result = evalAtCompileTime(c, result) @@ -1390,6 +1391,8 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = if tfHasAsgn in lhs.typ.flags and not lhsIsResult and mode != noOverloadedAsgn: return overloadedAsgn(c, lhs, n.sons[1]) + else: + liftTypeBoundOps(c, lhs.typ) fixAbstractType(c, n) asgnToResultVar(c, n, n.sons[0], n.sons[1]) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index c6e03cef3..3c26be89e 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -553,6 +553,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = # this can only happen for errornous var statements: if typ == nil: continue typeAllowedCheck(a.info, typ, symkind) + liftTypeBoundOps(c, typ) var tup = skipTypes(typ, {tyGenericInst, tyAlias}) if a.kind == nkVarTuple: if tup.kind != tyTuple: diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 172a557b3..5d0f0177c 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -363,11 +363,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = # '=' needs to be instantiated for generics when the type is constructed: newbody.field = cl.c.instTypeBoundOp(cl.c, opr, result, cl.info, attachedAsgn, 1) - # we need to produce the destructor first here because generated '=' - # and '=sink' operators can rely on it: - if newDestructors: typeBound(destructor) - typeBound(assignment) - typeBound(sink) + if not newDestructors: typeBound(assignment) let methods = skipTypes(bbody, abstractPtrs).methods for col, meth in items(methods): # we instantiate the known methods belonging to that type, this causes |