fixes #11004
This commit is contained in:
parent
041d15392a
commit
572735bbfa
2 changed files with 79 additions and 60 deletions
|
|
@ -27,9 +27,11 @@ type
|
||||||
recurse: bool
|
recurse: bool
|
||||||
c: PContext
|
c: PContext
|
||||||
|
|
||||||
proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode)
|
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
|
||||||
proc liftBody(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
info: TLineInfo): PSym {.discardable.}
|
info: TLineInfo): PSym
|
||||||
|
|
||||||
|
proc createTypeBoundOps*(c: PContext; orig: PType; info: TLineInfo)
|
||||||
|
|
||||||
proc at(a, i: PNode, elemType: PType): PNode =
|
proc at(a, i: PNode, elemType: PType): PNode =
|
||||||
result = newNodeI(nkBracketExpr, a.info, 2)
|
result = newNodeI(nkBracketExpr, a.info, 2)
|
||||||
|
|
@ -37,10 +39,10 @@ proc at(a, i: PNode, elemType: PType): PNode =
|
||||||
result.sons[1] = i
|
result.sons[1] = i
|
||||||
result.typ = elemType
|
result.typ = elemType
|
||||||
|
|
||||||
proc liftBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc fillBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
for i in 0 ..< t.len:
|
for i in 0 ..< t.len:
|
||||||
let lit = lowerings.newIntLit(c.graph, x.info, i)
|
let lit = lowerings.newIntLit(c.graph, x.info, i)
|
||||||
liftBodyAux(c, t.sons[i], body, x.at(lit, t.sons[i]), y.at(lit, t.sons[i]))
|
fillBody(c, t.sons[i], body, x.at(lit, t.sons[i]), y.at(lit, t.sons[i]))
|
||||||
|
|
||||||
proc dotField(x: PNode, f: PSym): PNode =
|
proc dotField(x: PNode, f: PSym): PNode =
|
||||||
result = newNodeI(nkDotExpr, x.info, 2)
|
result = newNodeI(nkDotExpr, x.info, 2)
|
||||||
|
|
@ -48,11 +50,11 @@ proc dotField(x: PNode, f: PSym): PNode =
|
||||||
result.sons[1] = newSymNode(f, x.info)
|
result.sons[1] = newSymNode(f, x.info)
|
||||||
result.typ = f.typ
|
result.typ = f.typ
|
||||||
|
|
||||||
proc liftBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
|
proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let f = n.sym
|
let f = n.sym
|
||||||
liftBodyAux(c, f.typ, body, x.dotField(f), y.dotField(f))
|
fillBody(c, f.typ, body, x.dotField(f), y.dotField(f))
|
||||||
of nkNilLit: discard
|
of nkNilLit: discard
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
if c.kind in {attachedSink, attachedAsgn, attachedDeepCopy}:
|
if c.kind in {attachedSink, attachedAsgn, attachedDeepCopy}:
|
||||||
|
|
@ -60,11 +62,11 @@ proc liftBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
|
||||||
## or the value is lost
|
## or the value is lost
|
||||||
let prevKind = c.kind
|
let prevKind = c.kind
|
||||||
c.kind = attachedDestructor
|
c.kind = attachedDestructor
|
||||||
liftBodyObj(c, n, body, x, y)
|
fillBodyObj(c, n, body, x, y)
|
||||||
c.kind = prevKind
|
c.kind = prevKind
|
||||||
|
|
||||||
# copy the selector:
|
# copy the selector:
|
||||||
liftBodyObj(c, n[0], body, x, y)
|
fillBodyObj(c, n[0], body, x, y)
|
||||||
# we need to generate a case statement:
|
# we need to generate a case statement:
|
||||||
var caseStmt = newNodeI(nkCaseStmt, c.info)
|
var caseStmt = newNodeI(nkCaseStmt, c.info)
|
||||||
# XXX generate 'if' that checks same branches
|
# XXX generate 'if' that checks same branches
|
||||||
|
|
@ -78,13 +80,13 @@ proc liftBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
|
||||||
let L = branch.len
|
let L = branch.len
|
||||||
branch.sons[L-1] = newNodeI(nkStmtList, c.info)
|
branch.sons[L-1] = newNodeI(nkStmtList, c.info)
|
||||||
|
|
||||||
liftBodyObj(c, n[i].lastSon, branch.sons[L-1], x, y)
|
fillBodyObj(c, n[i].lastSon, branch.sons[L-1], x, y)
|
||||||
if branch.sons[L-1].len == 0: inc emptyBranches
|
if branch.sons[L-1].len == 0: inc emptyBranches
|
||||||
caseStmt.add(branch)
|
caseStmt.add(branch)
|
||||||
if emptyBranches != n.len-1:
|
if emptyBranches != n.len-1:
|
||||||
body.add(caseStmt)
|
body.add(caseStmt)
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for t in items(n): liftBodyObj(c, t, body, x, y)
|
for t in items(n): fillBodyObj(c, t, body, x, y)
|
||||||
else:
|
else:
|
||||||
illFormedAstLocal(n, c.graph.config)
|
illFormedAstLocal(n, c.graph.config)
|
||||||
|
|
||||||
|
|
@ -150,7 +152,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||||
else:
|
else:
|
||||||
op = field
|
op = field
|
||||||
if op == nil:
|
if op == nil:
|
||||||
op = liftBody(c.c, t, c.kind, c.info)
|
op = produceSym(c.c, t, c.kind, c.info)
|
||||||
if sfError in op.flags:
|
if sfError in op.flags:
|
||||||
incl c.fn.flags, sfError
|
incl c.fn.flags, sfError
|
||||||
else:
|
else:
|
||||||
|
|
@ -172,7 +174,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||||
proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode): bool =
|
proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode): bool =
|
||||||
var op = t.destructor
|
var op = t.destructor
|
||||||
if op == nil and useNoGc(c, t):
|
if op == nil and useNoGc(c, t):
|
||||||
op = liftBody(c.c, t, attachedDestructor, c.info)
|
op = produceSym(c.c, t, attachedDestructor, c.info)
|
||||||
doAssert op != nil
|
doAssert op != nil
|
||||||
doAssert op == t.destructor
|
doAssert op == t.destructor
|
||||||
|
|
||||||
|
|
@ -280,12 +282,12 @@ proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
let i = declareCounter(c, body, firstOrd(c.graph.config, t))
|
let i = declareCounter(c, body, firstOrd(c.graph.config, t))
|
||||||
let whileLoop = genWhileLoop(c, i, x)
|
let whileLoop = genWhileLoop(c, i, x)
|
||||||
let elemType = t.lastSon
|
let elemType = t.lastSon
|
||||||
liftBodyAux(c, elemType, whileLoop.sons[1], x.at(i, elemType),
|
fillBody(c, elemType, whileLoop.sons[1], x.at(i, elemType),
|
||||||
y.at(i, elemType))
|
y.at(i, elemType))
|
||||||
addIncStmt(c, whileLoop.sons[1], i)
|
addIncStmt(c, whileLoop.sons[1], i)
|
||||||
body.add whileLoop
|
body.add whileLoop
|
||||||
|
|
||||||
proc seqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedAsgn, attachedDeepCopy:
|
of attachedAsgn, attachedDeepCopy:
|
||||||
# we generate:
|
# we generate:
|
||||||
|
|
@ -306,17 +308,31 @@ proc seqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
forallElements(c, t, body, x, y)
|
forallElements(c, t, body, x, y)
|
||||||
body.add genBuiltin(c.graph, mDestroy, "destroy", x)
|
body.add genBuiltin(c.graph, mDestroy, "destroy", x)
|
||||||
|
|
||||||
proc strOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
|
createTypeBoundOps(c.c, t, body.info)
|
||||||
|
case c.kind
|
||||||
|
of attachedAsgn, attachedDeepCopy:
|
||||||
|
doAssert t.assignment != nil
|
||||||
|
body.add newAsgnCall(c.graph, t.assignment, x, y)
|
||||||
|
of attachedSink:
|
||||||
|
# we always inline the move for better performance:
|
||||||
|
let moveCall = genBuiltin(c.graph, mMove, "move", x)
|
||||||
|
moveCall.add y
|
||||||
|
doAssert t.destructor != nil
|
||||||
|
moveCall.add destructorCall(c.graph, t.destructor, x)
|
||||||
|
body.add moveCall
|
||||||
|
# alternatively we could do this:
|
||||||
|
when false:
|
||||||
|
doAssert t.sink != nil
|
||||||
|
body.add newAsgnCall(c.graph, t.sink, x, y)
|
||||||
|
of attachedDestructor:
|
||||||
|
doAssert t.destructor != nil
|
||||||
|
body.add destructorCall(c.graph, t.destructor, x)
|
||||||
|
|
||||||
|
proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedAsgn, attachedDeepCopy:
|
of attachedAsgn, attachedDeepCopy:
|
||||||
body.add callCodegenProc(c.graph, "nimAsgnStrV2", c.info, genAddr(c.graph, x), y)
|
body.add callCodegenProc(c.graph, "nimAsgnStrV2", c.info, genAddr(c.graph, x), y)
|
||||||
# we generate:
|
|
||||||
# setLen(dest, y.len)
|
|
||||||
# var i = 0
|
|
||||||
# while i < y.len: dest[i] = y[i]; inc(i)
|
|
||||||
# This is usually more efficient than a destroy/create pair.
|
|
||||||
#body.add setLenStrCall(c.graph, x, y)
|
|
||||||
#forallElements(c, t, body, x, y)
|
|
||||||
of attachedSink:
|
of attachedSink:
|
||||||
let moveCall = genBuiltin(c.graph, mMove, "move", x)
|
let moveCall = genBuiltin(c.graph, mMove, "move", x)
|
||||||
moveCall.add y
|
moveCall.add y
|
||||||
|
|
@ -345,7 +361,7 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
var actions = newNodeI(nkStmtList, c.info)
|
var actions = newNodeI(nkStmtList, c.info)
|
||||||
|
|
||||||
let elemType = t.lastSon
|
let elemType = t.lastSon
|
||||||
#liftBodyAux(c, elemType, actions, genDeref(x), genDeref(y))
|
#fillBody(c, elemType, actions, genDeref(x), genDeref(y))
|
||||||
#var disposeCall = genBuiltin(c.graph, mDispose, "dispose", x)
|
#var disposeCall = genBuiltin(c.graph, mDispose, "dispose", x)
|
||||||
|
|
||||||
if isFinal(elemType):
|
if isFinal(elemType):
|
||||||
|
|
@ -406,7 +422,7 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
body.add genIf(c, xx, actions)
|
body.add genIf(c, xx, actions)
|
||||||
of attachedDeepCopy: assert(false, "cannot happen")
|
of attachedDeepCopy: assert(false, "cannot happen")
|
||||||
|
|
||||||
proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyNone, tyEmpty, tyVoid: discard
|
of tyNone, tyEmpty, tyVoid: discard
|
||||||
of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
|
of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
|
||||||
|
|
@ -442,7 +458,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
if useNoGc(c, t):
|
if useNoGc(c, t):
|
||||||
seqOp(c, t, body, x, y)
|
useSeqOrStrOp(c, t, body, x, y)
|
||||||
elif c.graph.config.selectedGC == gcDestructors:
|
elif c.graph.config.selectedGC == gcDestructors:
|
||||||
# note that tfHasAsgn is propagated so we need the check on
|
# note that tfHasAsgn is propagated so we need the check on
|
||||||
# 'selectedGC' here to determine if we have the new runtime.
|
# 'selectedGC' here to determine if we have the new runtime.
|
||||||
|
|
@ -455,19 +471,19 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tyString:
|
of tyString:
|
||||||
if useNoGc(c, t):
|
if useNoGc(c, t):
|
||||||
strOp(c, t, body, x, y)
|
useSeqOrStrOp(c, t, body, x, y)
|
||||||
elif tfHasAsgn in t.flags:
|
elif tfHasAsgn in t.flags:
|
||||||
discard considerUserDefinedOp(c, t, body, x, y)
|
discard considerUserDefinedOp(c, t, body, x, y)
|
||||||
else:
|
else:
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
if not considerUserDefinedOp(c, t, body, x, y):
|
if not considerUserDefinedOp(c, t, body, x, y):
|
||||||
liftBodyObj(c, t.n, body, x, y)
|
fillBodyObj(c, t.n, body, x, y)
|
||||||
of tyDistinct:
|
of tyDistinct:
|
||||||
if not considerUserDefinedOp(c, t, body, x, y):
|
if not considerUserDefinedOp(c, t, body, x, y):
|
||||||
liftBodyAux(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
|
fillBody(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
liftBodyTup(c, t, body, x, y)
|
fillBodyTup(c, t, body, x, y)
|
||||||
of tyVarargs, tyOpenArray:
|
of tyVarargs, tyOpenArray:
|
||||||
localError(c.graph.config, c.info, "cannot copy openArray")
|
localError(c.graph.config, c.info, "cannot copy openArray")
|
||||||
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
|
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
|
||||||
|
|
@ -478,45 +494,40 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
discard
|
discard
|
||||||
of tyVar, tyLent:
|
of tyVar, tyLent:
|
||||||
if c.kind != attachedDestructor:
|
if c.kind != attachedDestructor:
|
||||||
liftBodyAux(c, lastSon(t), body, x, y)
|
fillBody(c, lastSon(t), body, x, y)
|
||||||
of tyOrdinal, tyRange, tyInferred,
|
of tyOrdinal, tyRange, tyInferred,
|
||||||
tyGenericInst, tyStatic, tyAlias, tySink:
|
tyGenericInst, tyStatic, tyAlias, tySink:
|
||||||
liftBodyAux(c, lastSon(t), body, x, y)
|
fillBody(c, lastSon(t), body, x, y)
|
||||||
|
|
||||||
proc liftBodyDistinctType(c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
proc produceSymDistinctType(c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
||||||
assert typ.kind == tyDistinct
|
assert typ.kind == tyDistinct
|
||||||
let baseType = typ[0]
|
let baseType = typ[0]
|
||||||
case kind
|
case kind
|
||||||
of attachedAsgn:
|
of attachedAsgn:
|
||||||
if baseType.assignment == nil:
|
if baseType.assignment == nil:
|
||||||
discard liftBody(c, baseType, kind, info)
|
discard produceSym(c, baseType, kind, info)
|
||||||
typ.assignment = baseType.assignment
|
typ.assignment = baseType.assignment
|
||||||
result = typ.assignment
|
result = typ.assignment
|
||||||
of attachedSink:
|
of attachedSink:
|
||||||
if baseType.sink == nil:
|
if baseType.sink == nil:
|
||||||
discard liftBody(c, baseType, kind, info)
|
discard produceSym(c, baseType, kind, info)
|
||||||
typ.sink = baseType.sink
|
typ.sink = baseType.sink
|
||||||
result = typ.sink
|
result = typ.sink
|
||||||
of attachedDeepCopy:
|
of attachedDeepCopy:
|
||||||
if baseType.deepCopy == nil:
|
if baseType.deepCopy == nil:
|
||||||
discard liftBody(c, baseType, kind, info)
|
discard produceSym(c, baseType, kind, info)
|
||||||
typ.deepCopy = baseType.deepCopy
|
typ.deepCopy = baseType.deepCopy
|
||||||
result = typ.deepCopy
|
result = typ.deepCopy
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
if baseType.destructor == nil:
|
if baseType.destructor == nil:
|
||||||
discard liftBody(c, baseType, kind, info)
|
discard produceSym(c, baseType, kind, info)
|
||||||
typ.destructor = baseType.destructor
|
typ.destructor = baseType.destructor
|
||||||
result = typ.destructor
|
result = typ.destructor
|
||||||
|
|
||||||
proc liftBody(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
if typ.kind == tyDistinct:
|
if typ.kind == tyDistinct:
|
||||||
return liftBodyDistinctType(c, typ, kind, info)
|
return produceSymDistinctType(c, typ, kind, info)
|
||||||
when false:
|
|
||||||
var typ = typ
|
|
||||||
if c.config.selectedGC == gcDestructors and typ.kind == tySequence:
|
|
||||||
# use the canonical type to access the =sink and =destroy etc.
|
|
||||||
typ = c.graph.sysTypes[tySequence]
|
|
||||||
|
|
||||||
var a: TLiftCtx
|
var a: TLiftCtx
|
||||||
a.info = info
|
a.info = info
|
||||||
|
|
@ -552,7 +563,18 @@ proc liftBody(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
of attachedDeepCopy: typ.deepCopy = result
|
of attachedDeepCopy: typ.deepCopy = result
|
||||||
of attachedDestructor: typ.destructor = result
|
of attachedDestructor: typ.destructor = result
|
||||||
|
|
||||||
liftBodyAux(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
|
var tk: TTypeKind
|
||||||
|
if optNimV2 in c.graph.config.globalOptions:
|
||||||
|
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
|
||||||
|
else:
|
||||||
|
tk = tyNone # no special casing for strings and seqs
|
||||||
|
case tk
|
||||||
|
of tySequence:
|
||||||
|
fillSeqOp(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
|
||||||
|
of tyString:
|
||||||
|
fillStrOp(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
|
||||||
|
else:
|
||||||
|
fillBody(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
|
||||||
|
|
||||||
var n = newNodeI(nkProcDef, info, bodyPos+1)
|
var n = newNodeI(nkProcDef, info, bodyPos+1)
|
||||||
for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info)
|
for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info)
|
||||||
|
|
@ -563,16 +585,6 @@ proc liftBody(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
incl result.flags, sfFromGeneric
|
incl result.flags, sfFromGeneric
|
||||||
incl result.flags, sfGeneratedOp
|
incl result.flags, sfGeneratedOp
|
||||||
|
|
||||||
proc getAsgnOrLiftBody(c: PContext; typ: PType; info: TLineInfo): PSym =
|
|
||||||
let t = typ.skipTypes({tyGenericInst, tyVar, tyLent, tyAlias, tySink})
|
|
||||||
result = t.assignment
|
|
||||||
if result.isNil:
|
|
||||||
result = liftBody(c, t, attachedAsgn, info)
|
|
||||||
|
|
||||||
proc overloadedAsgn(c: PContext; dest, src: PNode): PNode =
|
|
||||||
let a = getAsgnOrLiftBody(c, dest.typ, dest.info)
|
|
||||||
result = newAsgnCall(c.graph, a, dest, src)
|
|
||||||
|
|
||||||
template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
|
template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
|
||||||
discard "now a nop"
|
discard "now a nop"
|
||||||
|
|
||||||
|
|
@ -581,7 +593,7 @@ proc patchBody(c: PContext; n: PNode; info: TLineInfo) =
|
||||||
if n[0].kind == nkSym and n[0].sym.magic == mDestroy:
|
if n[0].kind == nkSym and n[0].sym.magic == mDestroy:
|
||||||
let t = n[1].typ.skipTypes(abstractVar)
|
let t = n[1].typ.skipTypes(abstractVar)
|
||||||
if t.destructor == nil:
|
if t.destructor == nil:
|
||||||
liftBody(c, t, attachedDestructor, info)
|
discard produceSym(c, t, attachedDestructor, info)
|
||||||
|
|
||||||
if t.destructor != nil:
|
if t.destructor != nil:
|
||||||
if t.destructor.ast[genericParamsPos].kind != nkEmpty:
|
if t.destructor.ast[genericParamsPos].kind != nkEmpty:
|
||||||
|
|
@ -600,7 +612,7 @@ template inst(field, t) =
|
||||||
|
|
||||||
proc isTrival(s: PSym): bool {.inline.} = s == nil or s.ast[bodyPos].len == 0
|
proc isTrival(s: PSym): bool {.inline.} = s == nil or s.ast[bodyPos].len == 0
|
||||||
|
|
||||||
proc createTypeBoundOps*(c: PContext; orig: PType; info: TLineInfo) =
|
proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
|
||||||
## In the semantic pass this is called in strategic places
|
## In the semantic pass this is called in strategic places
|
||||||
## to ensure we lift assignment, destructors and moves properly.
|
## to ensure we lift assignment, destructors and moves properly.
|
||||||
## The later 'injectdestructors' pass depends on it.
|
## The later 'injectdestructors' pass depends on it.
|
||||||
|
|
@ -625,15 +637,15 @@ proc createTypeBoundOps*(c: PContext; orig: PType; info: TLineInfo) =
|
||||||
let typ = canon.skipTypes({tyGenericInst, tyAlias})
|
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:
|
||||||
if typ.destructor == nil:
|
if typ.destructor == nil:
|
||||||
liftBody(c, typ, attachedDestructor, info)
|
discard produceSym(c, typ, attachedDestructor, info)
|
||||||
else:
|
else:
|
||||||
inst(typ.destructor, typ)
|
inst(typ.destructor, typ)
|
||||||
if typ.assignment == nil:
|
if typ.assignment == nil:
|
||||||
liftBody(c, typ, attachedAsgn, info)
|
discard produceSym(c, typ, attachedAsgn, info)
|
||||||
else:
|
else:
|
||||||
inst(typ.assignment, typ)
|
inst(typ.assignment, typ)
|
||||||
if typ.sink == nil:
|
if typ.sink == nil:
|
||||||
liftBody(c, typ, attachedSink, info)
|
discard produceSym(c, typ, attachedSink, info)
|
||||||
else:
|
else:
|
||||||
inst(typ.sink, typ)
|
inst(typ.sink, typ)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ import strutils, os
|
||||||
import core / allocators
|
import core / allocators
|
||||||
import system / ansi_c
|
import system / ansi_c
|
||||||
|
|
||||||
|
# bug #11004
|
||||||
|
proc retTuple(): (seq[int], int) =
|
||||||
|
# XXX this doesn't allocate yet but probably it should
|
||||||
|
return (@[1], 1)
|
||||||
|
|
||||||
proc nonStaticTests =
|
proc nonStaticTests =
|
||||||
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
|
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
|
||||||
when not defined(js):
|
when not defined(js):
|
||||||
|
|
@ -177,6 +182,8 @@ proc staticTests =
|
||||||
doAssert s.splitWhitespace(maxsplit=3) == @["this", "is", "an", "example "]
|
doAssert s.splitWhitespace(maxsplit=3) == @["this", "is", "an", "example "]
|
||||||
doAssert s.splitWhitespace(maxsplit=4) == @["this", "is", "an", "example"]
|
doAssert s.splitWhitespace(maxsplit=4) == @["this", "is", "an", "example"]
|
||||||
|
|
||||||
|
discard retTuple()
|
||||||
|
|
||||||
nonStaticTests()
|
nonStaticTests()
|
||||||
staticTests()
|
staticTests()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue