diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim index f831d33cc9e4b..49221654d3204 100644 --- a/compiler/varpartitions.nim +++ b/compiler/varpartitions.nim @@ -545,6 +545,9 @@ proc borrowingCall(c: var Partitions; destType: PType; n: PNode; i: int) = localError(c.config, n[i].info, "cannot determine the target of the borrow") proc borrowingAsgn(c: var Partitions; dest, src: PNode) = + proc mutableParameter(n: PNode): bool {.inline.} = + result = n.kind == nkSym and n.sym.kind == skParam and n.sym.typ.kind == tyVar + if dest.kind == nkSym: if directViewType(dest.typ) != noView: borrowFrom(c, dest.sym, src) @@ -559,7 +562,11 @@ proc borrowingAsgn(c: var Partitions; dest, src: PNode) = if vid >= 0: c.s[vid].flags.incl viewDoesMutate of immutableView: - localError(c.config, dest.info, "attempt to mutate a borrowed location from an immutable view") + if dest.kind == nkBracketExpr and dest[0].kind == nkHiddenDeref and + mutableParameter(dest[0][0]): + discard "remains a mutable location anyhow" + else: + localError(c.config, dest.info, "attempt to mutate a borrowed location from an immutable view") of noView: discard "nothing to do" proc containsPointer(t: PType): bool = diff --git a/tests/views/tcan_compile_nim.nim b/tests/views/tcan_compile_nim.nim new file mode 100644 index 0000000000000..e990606cde292 --- /dev/null +++ b/tests/views/tcan_compile_nim.nim @@ -0,0 +1,4 @@ +discard """ + cmd: "nim check --hints:on --experimental:strictFuncs --experimental:views compiler/nim.nim" + action: "compile" +""" diff --git a/tests/views/tdont_mutate.nim b/tests/views/tdont_mutate.nim index 907aff018ac34..d243c7c7afe7f 100644 --- a/tests/views/tdont_mutate.nim +++ b/tests/views/tdont_mutate.nim @@ -46,3 +46,14 @@ proc main() = echo i, ": ", x main() + +# This has to continue to work: + +type + PNode = ref object + TSrcGen = object + comStack: seq[PNode] + +proc pushCom(g: var TSrcGen, n: PNode) = + setLen(g.comStack, g.comStack.len + 1) + g.comStack[^1] = n