@@ -493,6 +493,25 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
493493 # no need to destroy it.
494494 result .add tmp
495495
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+
496515proc ensureDestruction (arg, orig: PNode ; c: var Con ; s: var Scope ): PNode =
497516 # it can happen that we need to destroy expression contructors
498517 # 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
776795 template process (child, s): untyped = p (child, c, s, mode)
777796 handleNestedTempl (n, process, tmpFlags = tmpFlags)
778797 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} +
780804 nkCallKinds + nkLiterals:
781805 result = p (n, c, s, consumed)
782806 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
11431167 dec c.inEnsureMove, isEnsureMove
11441168 result .add p (ri, c, s, consumed)
11451169 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:
11471181 result = c.genSink (s, dest, p (ri, c, s, consumed), flags)
11481182 of nkSym:
11491183 if isSinkParam (ri.sym) and isLastRead (ri, c, s):
0 commit comments