This commit is contained in:
Andreas Rumpf 2020-10-07 14:38:25 +02:00 • committed by GitHub
commit 0426a4d85a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 6 deletions

View file

@ -48,7 +48,8 @@ proc dec(x: var AbstractTime; diff = 1) {.borrow.}
type type
SubgraphFlag = enum SubgraphFlag = enum
isMutated, # graph might be mutated 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 VarFlag = enum
ownsData, ownsData,
@ -99,12 +100,12 @@ type
config: ConfigRef config: ConfigRef
proc mutationAfterConnection(g: MutationInfo): bool {.inline.} = 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 g.maxMutation > g.minConnection
proc `$`*(config: ConfigRef; g: MutationInfo): string = proc `$`*(config: ConfigRef; g: MutationInfo): string =
result = "" result = ""
if g.flags == {isMutated, connectsConstParam}: if g.flags * {isMutated, connectsConstParam} == {isMutated, connectsConstParam}:
result.add "\nan object reachable from '" result.add "\nan object reachable from '"
result.add g.param.name.s result.add g.param.name.s
result.add "' is potentially mutated" result.add "' is potentially mutated"
@ -119,7 +120,8 @@ proc `$`*(config: ConfigRef; g: MutationInfo): string =
proc hasSideEffect*(c: var Partitions; info: var MutationInfo): bool = proc hasSideEffect*(c: var Partitions; info: var MutationInfo): bool =
for g in mitems c.graphs: 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 info = g
return true return true
return false return false
@ -173,11 +175,16 @@ proc potentialMutation(v: var Partitions; s: PSym; info: TLineInfo) =
let id = variableId(v, s) let id = variableId(v, s)
if id >= 0: if id >= 0:
let r = root(v, id) let r = root(v, id)
let flags = if s.kind == skParam and isConstParam(s):
{isMutated, isMutatedDirectly}
else:
{isMutated}
case v.s[r].con.kind case v.s[r].con.kind
of isEmptyRoot: of isEmptyRoot:
v.s[r].con = Connection(kind: isRootOf, graphIndex: v.graphs.len) v.s[r].con = Connection(kind: isRootOf, graphIndex: v.graphs.len)
v.graphs.add MutationInfo(param: if isConstParam(s): s else: nil, mutatedHere: info, 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, maxMutation: v.abstractTime, minConnection: MaxTime,
mutations: @[v.abstractTime]) mutations: @[v.abstractTime])
of isRootOf: of isRootOf:
@ -187,7 +194,7 @@ proc potentialMutation(v: var Partitions; s: PSym; info: TLineInfo) =
if v.abstractTime > g.maxMutation: if v.abstractTime > g.maxMutation:
g.mutatedHere = info g.mutatedHere = info
g.maxMutation = v.abstractTime g.maxMutation = v.abstractTime
g.flags.incl isMutated g.flags.incl flags
g.mutations.add v.abstractTime g.mutations.add v.abstractTime
else: else:
assert false, "cannot happen" assert false, "cannot happen"

View file

@ -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