diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 6bf1e5fdf3..ee0dcc9b4e 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -155,7 +155,7 @@ proc reifiedOpenArray(n: PNode): bool {.inline.} = else: result = true -proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope, Rope) = +proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType; prepareForMutation = false): (Rope, Rope) = var a, b, c: TLoc initLocExpr(p, q[1], a) initLocExpr(p, q[2], b) @@ -163,6 +163,8 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope, # but first produce the required index checks: if optBoundsCheck in p.options: genBoundsCheck(p, a, b, c) + if prepareForMutation: + linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)]) let ty = skipTypes(a.t, abstractVar+{tyPtr}) let dest = getTypeDesc(p.module, destType) let lengthExpr = "($1)-($2)+1" % [rdLoc(c), rdLoc(b)] diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 0ca650a7e3..09dd780c88 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2299,7 +2299,10 @@ proc genDispose(p: BProc; n: PNode) = lineCg(p, cpsStmts, ["#nimDestroyAndDispose($#)", rdLoc(a)]) proc genSlice(p: BProc; e: PNode; d: var TLoc) = - let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.lastSon) + let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.lastSon, + prepareForMutation = e[1].kind == nkHiddenDeref and + e[1].typ.skipTypes(abstractInst).kind == tyString and + p.config.selectedGC in {gcArc, gcOrc}) if d.k == locNone: getTemp(p, e.typ, d) linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $3;$n", [rdLoc(d), x, y]) when false: diff --git a/tests/arc/topenarray.nim b/tests/arc/topenarray.nim index 47c26a11f8..0e45f3ec7b 100644 --- a/tests/arc/topenarray.nim +++ b/tests/arc/topenarray.nim @@ -6,6 +6,8 @@ Nim ''' matrix: "--gc:arc -d:useMalloc; --gc:arc" """ +{.experimental: "views".} + block: # bug 18627 proc setPosition(params: openArray[string]) = for i in params.toOpenArray(0, params.len - 1): @@ -38,3 +40,13 @@ block: # bug #20954 var v: seq[int] echo len(toOpenArray(v, 20, 30)) + +# bug #20422 + +proc f(a: var string) = + var v = a.toOpenArray(1, 3) + v[0] = 'a' + +var a = "Hello" +f(a) +doAssert a == "Hallo"