fixes #2286
This commit is contained in:
parent
5a21892da0
commit
f514be0772
4 changed files with 77 additions and 22 deletions
|
|
@ -203,6 +203,17 @@ proc flowVarKind(t: PType): TFlowVarKind =
|
|||
elif containsGarbageCollectedRef(t): fvInvalid
|
||||
else: fvBlob
|
||||
|
||||
proc typeNeedsNoDeepCopy(t: PType): bool =
|
||||
var t = t.skipTypes(abstractInst)
|
||||
# for the tconvexhull example (and others) we're a bit lax here and pretend
|
||||
# seqs and strings are *by value* only and 'shallow' doesn't exist!
|
||||
if t.kind == tyString: return true
|
||||
# note that seq[T] is fine, but 'var seq[T]' is not, so we need to skip 'var'
|
||||
# for the stricter check and likewise we can skip 'seq' for a less
|
||||
# strict check:
|
||||
if t.kind in {tyVar, tySequence}: t = t.sons[0]
|
||||
result = not containsGarbageCollectedRef(t)
|
||||
|
||||
proc addLocalVar(varSection, varInit: PNode; owner: PSym; typ: PType;
|
||||
v: PNode; useShallowCopy=false): PSym =
|
||||
result = newSym(skTemp, getIdent(genPrefix), owner, varSection.info)
|
||||
|
|
@ -215,7 +226,7 @@ proc addLocalVar(varSection, varInit: PNode; owner: PSym; typ: PType;
|
|||
vpart.sons[2] = if varInit.isNil: v else: ast.emptyNode
|
||||
varSection.add vpart
|
||||
if varInit != nil:
|
||||
if useShallowCopy:
|
||||
if useShallowCopy and typeNeedsNoDeepCopy(typ):
|
||||
varInit.add newFastAsgnStmt(newSymNode(result), v)
|
||||
else:
|
||||
let deepCopyCall = newNodeI(nkCall, varInit.info, 3)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ true
|
|||
true
|
||||
true'''
|
||||
|
||||
ccodeCheck: "!'deepcopy('"
|
||||
ccodeCheck: "\\i ! @'deepCopy(' .*"
|
||||
"""
|
||||
|
||||
# parallel convex hull for Nim bigbreak
|
||||
|
|
|
|||
40
tests/parallel/tmissing_deepcopy.nim
Normal file
40
tests/parallel/tmissing_deepcopy.nim
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
discard """
|
||||
ccodeCheck: "\\i @'deepCopy(' .*"
|
||||
"""
|
||||
|
||||
# bug #2286
|
||||
|
||||
import threadPool
|
||||
|
||||
type
|
||||
Person = ref object
|
||||
name: string
|
||||
friend: Person
|
||||
|
||||
var
|
||||
people: seq[Person] = @[]
|
||||
|
||||
proc newPerson(name:string): Person =
|
||||
result.new()
|
||||
result.name = name
|
||||
|
||||
proc greet(p:Person) =
|
||||
p.friend.name &= "-MUT" # this line crashes the program
|
||||
echo "Person {",
|
||||
" name:", p.name, "(", cast[int](addr p.name),"),",
|
||||
" friend:", p.friend.name, "(", cast[int](addr p.friend.name),") }"
|
||||
|
||||
proc setup =
|
||||
for i in 0 .. <20:
|
||||
people.add newPerson("Person" & $(i + 1))
|
||||
for i in 0 .. <20:
|
||||
people[i].friend = people[19-i]
|
||||
|
||||
proc update =
|
||||
parallel:
|
||||
for i in 0 .. people.high:
|
||||
spawn people[i].greet()
|
||||
|
||||
when isMainModule:
|
||||
setup()
|
||||
update()
|
||||
|
|
@ -148,7 +148,11 @@ proc codegenCheck(test: TTest, check: string, given: var TSpec) =
|
|||
let genFile = generatedFile(path, name, test.target)
|
||||
echo genFile
|
||||
let contents = readFile(genFile).string
|
||||
if contents.find(check.peg) < 0:
|
||||
if check[0] == '\\':
|
||||
# little hack to get 'match' support:
|
||||
if not contents.match(check.peg):
|
||||
given.err = reCodegenFailure
|
||||
elif contents.find(check.peg) < 0:
|
||||
given.err = reCodegenFailure
|
||||
except ValueError:
|
||||
given.err = reInvalidPeg
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue