@@ -493,6 +493,25 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
493
493
# no need to destroy it.
494
494
result .add tmp
495
495
496
+ proc isDangerousSeq(t: PType): bool {.inline.} =
497
+ let t = t.skipTypes(abstractInst)
498
+ result = t.kind == tySequence and tfHasOwned notin t.elementType.flags
499
+
500
+ proc containsConstSeq(n: PNode): bool =
501
+ if n.kind == nkBracket and n.len > 0 and n.typ != nil and isDangerousSeq(n.typ):
502
+ return true
503
+ result = false
504
+ case n.kind
505
+ of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv, nkCast:
506
+ result = containsConstSeq(n[1 ])
507
+ of nkObjConstr, nkClosure:
508
+ for i in 1 ..< n.len:
509
+ if containsConstSeq(n[i]) : return true
510
+ of nkCurly, nkBracket, nkPar, nkTupleConstr:
511
+ for son in n:
512
+ if containsConstSeq(son): return true
513
+ else : discard
514
+
496
515
proc ensureDestruction(arg, orig: PNode; c: var Con; s: var Scope): PNode =
497
516
# it can happen that we need to destroy expression contructors
498
517
# like [], (), closures explicitly in order to not leak them.
@@ -776,7 +795,12 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
776
795
template process(child, s): untyped = p(child, c, s, mode)
777
796
handleNestedTempl(n, process, tmpFlags = tmpFlags)
778
797
elif mode == sinkArg:
779
- if n.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure, nkNilLit} +
798
+ if n.containsConstSeq:
799
+ # const sequences are not mutable and so we need to pass a copy to the
800
+ # sink parameter (bug #11524). Note that the string implementation is
801
+ # different and can deal with 'const string sunk into var'.
802
+ result = passCopyToSink(n, c, s)
803
+ elif n.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure, nkNilLit} +
780
804
nkCallKinds + nkLiterals:
781
805
result = p(n, c, s, consumed)
782
806
elif ((n.kind == nkSym and isSinkParam(n.sym)) or isAnalysableFieldAccess(n, c.owner)) and
@@ -1143,7 +1167,17 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
1143
1167
dec c.inEnsureMove, isEnsureMove
1144
1168
result .add p(ri, c, s, consumed)
1145
1169
c.finishCopy(result , dest, flags, isFromSink = false )
1146
- of nkBracket, nkObjConstr, nkTupleConstr, nkClosure, nkCharLit.. nkNilLit:
1170
+ of nkBracket:
1171
+ # array constructor
1172
+ if ri.len > 0 and isDangerousSeq(ri.typ):
1173
+ inc c.inEnsureMove, isEnsureMove
1174
+ result = c.genCopy(dest, ri, flags)
1175
+ dec c.inEnsureMove, isEnsureMove
1176
+ result .add p(ri, c, s, consumed)
1177
+ c.finishCopy(result , dest, flags, isFromSink = false )
1178
+ else :
1179
+ result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
1180
+ of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit.. nkNilLit:
1147
1181
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
1148
1182
of nkSym:
1149
1183
if isSinkParam(ri.sym) and isLastRead(ri, c, s):
0 commit comments