diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-10-07 14:38:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-07 14:38:25 +0200 |
commit | 0426a4d85ab8f9558dee35c657aad0d299748c15 (patch) | |
tree | 14dfd278c4e727f50b0d494100043755ccaee5fe | |
parent | acbe27b082c202895df1b78a82951389b4a232a0 (diff) | |
download | Nim-0426a4d85ab8f9558dee35c657aad0d299748c15.tar.gz |
fixes #15508 (#15509)
-rw-r--r-- | compiler/varpartitions.nim | 19 | ||||
-rw-r--r-- | tests/effects/tfuncs_cannot_mutate_simple.nim | 21 |
2 files changed, 34 insertions, 6 deletions
diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim index a172a906e..f831d33cc 100644 --- a/compiler/varpartitions.nim +++ b/compiler/varpartitions.nim @@ -48,7 +48,8 @@ proc dec(x: var AbstractTime; diff = 1) {.borrow.} type SubgraphFlag = enum isMutated, # graph might be mutated - connectsConstParam, # graph is connected to a non-var parameter. + isMutatedDirectly, # graph is mutated directly by a non-var parameter. + connectsConstParam # graph is connected to a non-var parameter. VarFlag = enum ownsData, @@ -99,12 +100,12 @@ type config: ConfigRef proc mutationAfterConnection(g: MutationInfo): bool {.inline.} = - #echo g.maxMutation, " ", g.minConnection, " ", g.param + #echo g.maxMutation.int, " ", g.minConnection.int, " ", g.param g.maxMutation > g.minConnection proc `$`*(config: ConfigRef; g: MutationInfo): string = result = "" - if g.flags == {isMutated, connectsConstParam}: + if g.flags * {isMutated, connectsConstParam} == {isMutated, connectsConstParam}: result.add "\nan object reachable from '" result.add g.param.name.s result.add "' is potentially mutated" @@ -119,7 +120,8 @@ proc `$`*(config: ConfigRef; g: MutationInfo): string = proc hasSideEffect*(c: var Partitions; info: var MutationInfo): bool = for g in mitems c.graphs: - if g.flags == {isMutated, connectsConstParam} and mutationAfterConnection(g): + if g.flags * {isMutated, connectsConstParam} == {isMutated, connectsConstParam} and + (mutationAfterConnection(g) or isMutatedDirectly in g.flags): info = g return true return false @@ -173,11 +175,16 @@ proc potentialMutation(v: var Partitions; s: PSym; info: TLineInfo) = let id = variableId(v, s) if id >= 0: let r = root(v, id) + let flags = if s.kind == skParam and isConstParam(s): + {isMutated, isMutatedDirectly} + else: + {isMutated} + case v.s[r].con.kind of isEmptyRoot: v.s[r].con = Connection(kind: isRootOf, graphIndex: v.graphs.len) v.graphs.add MutationInfo(param: if isConstParam(s): s else: nil, mutatedHere: info, - connectedVia: unknownLineInfo, flags: {isMutated}, + connectedVia: unknownLineInfo, flags: flags, maxMutation: v.abstractTime, minConnection: MaxTime, mutations: @[v.abstractTime]) of isRootOf: @@ -187,7 +194,7 @@ proc potentialMutation(v: var Partitions; s: PSym; info: TLineInfo) = if v.abstractTime > g.maxMutation: g.mutatedHere = info g.maxMutation = v.abstractTime - g.flags.incl isMutated + g.flags.incl flags g.mutations.add v.abstractTime else: assert false, "cannot happen" diff --git a/tests/effects/tfuncs_cannot_mutate_simple.nim b/tests/effects/tfuncs_cannot_mutate_simple.nim new file mode 100644 index 000000000..9de20d1ec --- /dev/null +++ b/tests/effects/tfuncs_cannot_mutate_simple.nim @@ -0,0 +1,21 @@ +discard """ + errormsg: "'edit' can have side effects" + nimout: '''an object reachable from 'x' is potentially mutated +tfuncs_cannot_mutate_simple.nim(17, 4) the mutation is here''' + line: 16 +""" + +{.experimental: "strictFuncs".} + +# bug #15508 + +type + MyType = ref object + data: string + +func edit(x: MyType) = + x.data = "hello" + +let x = MyType() +x.edit() +echo x.data |