tmovebugcopy.nim 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. discard """
  2. cmd: "nim c --gc:arc $file"
  3. output: '''5
  4. (w: 5)
  5. (w: -5)
  6. c.text = hello
  7. c.text = hello
  8. p.text = hello
  9. p.toks = @["hello"]
  10. c.text = hello
  11. c[].text = hello
  12. pA.text = hello
  13. pA.toks = @["hello"]
  14. c.text = hello
  15. c.text = hello
  16. pD.text = hello
  17. pD.toks = @["hello"]
  18. c.text = hello
  19. c.text = hello
  20. pOD.text = hello
  21. pOD.toks = @["hello"]
  22. fff
  23. fff
  24. 2
  25. fff
  26. fff
  27. 2
  28. fff
  29. fff
  30. 2
  31. mmm
  32. fff
  33. fff
  34. fff
  35. 3
  36. mmm
  37. sink me (sink)
  38. assign me (not sink)
  39. sink me (not sink)
  40. sinked and not optimized to a bitcopy
  41. sinked and not optimized to a bitcopy
  42. sinked and not optimized to a bitcopy
  43. (data: @[0, 0])
  44. (data: @[0, 0])
  45. (data: @[0, 0])
  46. (data: @[0, 0])
  47. (data: @[0, 0])
  48. (data: @[0, 0])
  49. (data: @[0, 0])
  50. 100
  51. hey
  52. hey
  53. (a: "a", b: 2)
  54. ho
  55. (a: "b", b: 3)
  56. (b: "b", a: 2)
  57. ho
  58. (b: "a", a: 3)
  59. hey
  60. break
  61. break
  62. hey
  63. ho
  64. hey
  65. ho
  66. ho
  67. king
  68. live long; long live
  69. king
  70. hi
  71. try
  72. bye
  73. '''
  74. """
  75. # move bug
  76. type
  77. TMyObj = object
  78. p: pointer
  79. len: int
  80. var destroyCounter = 0
  81. proc `=destroy`(o: var TMyObj) =
  82. if o.p != nil:
  83. dealloc o.p
  84. o.p = nil
  85. inc destroyCounter
  86. proc `=copy`(dst: var TMyObj, src: TMyObj) =
  87. `=destroy`(dst)
  88. dst.p = alloc(src.len)
  89. dst.len = src.len
  90. proc `=sink`(dst: var TMyObj, src: TMyObj) =
  91. `=destroy`(dst)
  92. dst.p = src.p
  93. dst.len = src.len
  94. type
  95. TObjKind = enum Z, A, B
  96. TCaseObj = object
  97. case kind: TObjKind
  98. of Z: discard
  99. of A:
  100. x1: int # this int plays important role
  101. x2: TMyObj
  102. of B:
  103. y: TMyObj
  104. proc use(a: TCaseObj) = discard
  105. proc moveBug(i: var int) =
  106. var a: array[2, TCaseObj]
  107. a[i] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5))) # 1
  108. a[i+1] = a[i] # 2
  109. inc i
  110. use(a[i-1])
  111. var x = 0
  112. moveBug(x)
  113. proc moveBug2(): (TCaseObj, TCaseObj) =
  114. var a: array[2, TCaseObj]
  115. a[0] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5)))
  116. a[1] = a[0] # can move 3
  117. result[0] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5))) # 4
  118. result[1] = result[0] # 5
  119. proc main =
  120. discard moveBug2()
  121. main()
  122. echo destroyCounter
  123. # bug #13314
  124. type
  125. O = object
  126. v: int
  127. R = ref object
  128. w: int
  129. proc `$`(r: R): string = $r[]
  130. proc tbug13314 =
  131. var t5 = R(w: 5)
  132. var execute = proc () =
  133. echo t5
  134. execute()
  135. t5.w = -5
  136. execute()
  137. tbug13314()
  138. #-------------------------------------------------------------------------
  139. # bug #13368
  140. import strutils
  141. proc procStat() =
  142. for line in @["a b", "c d", "e f"]:
  143. let cols = line.splitWhitespace(maxSplit=1)
  144. let x = cols[0]
  145. let (nm, rest) = (cols[0], cols[1])
  146. procStat()
  147. # bug #14269
  148. import sugar, strutils
  149. type
  150. Cursor = object
  151. text: string
  152. Parsed = object
  153. text: string
  154. toks: seq[string]
  155. proc tokenize(c: var Cursor): seq[string] =
  156. dump c.text
  157. return c.text.splitWhitespace()
  158. proc parse(): Parsed =
  159. var c = Cursor(text: "hello")
  160. dump c.text
  161. return Parsed(text: c.text, toks: c.tokenize) # note: c.tokenized uses c.text
  162. let p = parse()
  163. dump p.text
  164. dump p.toks
  165. proc tokenizeA(c: ptr Cursor): seq[string] =
  166. dump c[].text
  167. return c[].text.splitWhitespace()
  168. proc parseA(): Parsed =
  169. var c = Cursor(text: "hello")
  170. dump c.text
  171. return Parsed(text: c.text, toks: c.addr.tokenizeA) # note: c.tokenized uses c.text
  172. let pA = parseA()
  173. dump pA.text
  174. dump pA.toks
  175. proc tokenizeD(c: Cursor): seq[string] =
  176. dump c.text
  177. return c.text.splitWhitespace()
  178. proc parseD(): Parsed =
  179. var c = cast[ptr Cursor](alloc0(sizeof(Cursor)))
  180. c[] = Cursor(text: "hello")
  181. dump c.text
  182. return Parsed(text: c.text, toks: c[].tokenizeD) # note: c.tokenized uses c.text
  183. let pD = parseD()
  184. dump pD.text
  185. dump pD.toks
  186. # Bug would only pop up with owned refs
  187. proc tokenizeOD(c: Cursor): seq[string] =
  188. dump c.text
  189. return c.text.splitWhitespace()
  190. proc parseOD(): Parsed =
  191. var c = new Cursor
  192. c[] = Cursor(text: "hello")
  193. dump c.text
  194. return Parsed(text: c.text, toks: c[].tokenizeOD) # note: c.tokenized uses c.text
  195. let pOD = parseOD()
  196. dump pOD.text
  197. dump pOD.toks
  198. when false:
  199. # Bug would only pop up with owned refs and implicit derefs, but since they don't work together..
  200. {.experimental: "implicitDeref".}
  201. proc tokenizeOHD(c: Cursor): seq[string] =
  202. dump c.text
  203. return c.text.splitWhitespace()
  204. proc parseOHD(): Parsed =
  205. var c = new Cursor
  206. c[] = Cursor(text: "hello")
  207. dump c.text
  208. return Parsed(text: c.text, toks: c.tokenizeOHD) # note: c.tokenized uses c.text
  209. let pOHD = parseOHD()
  210. dump pOHD.text
  211. dump pOHD.toks
  212. # bug #13456
  213. iterator combinations[T](s: openarray[T], k: int): seq[T] =
  214. let n = len(s)
  215. assert k >= 0 and k <= n
  216. var pos = newSeq[int](k)
  217. var current = newSeq[T](k)
  218. for i in 0..k-1:
  219. pos[k-i-1] = i
  220. var done = false
  221. while not done:
  222. for i in 0..k-1:
  223. current[i] = s[pos[k-i-1]]
  224. yield current
  225. var i = 0
  226. while i < k:
  227. pos[i] += 1
  228. if pos[i] < n-i:
  229. for j in 0..i-1:
  230. pos[j] = pos[i] + i - j
  231. break
  232. i += 1
  233. if i >= k:
  234. break
  235. type
  236. UndefEx = object of ValueError
  237. proc main2 =
  238. var delayedSyms = @[1, 2, 3]
  239. var unp: seq[int]
  240. block myb:
  241. for a in 1 .. 2:
  242. if delayedSyms.len > a:
  243. unp = delayedSyms
  244. for t in unp.combinations(a + 1):
  245. try:
  246. var h = false
  247. for k in t:
  248. echo "fff"
  249. if h: continue
  250. if true:
  251. raise newException(UndefEx, "forward declaration")
  252. break myb
  253. except UndefEx:
  254. echo t.len
  255. echo "mmm"
  256. main2()
  257. type ME = object
  258. who: string
  259. proc `=copy`(x: var ME, y: ME) =
  260. if y.who.len > 0: echo "assign ",y.who
  261. proc `=sink`(x: var ME, y: ME) =
  262. if y.who.len > 0: echo "sink ",y.who
  263. var dump: ME
  264. template use(x) = dump = x
  265. template def(x) = x = dump
  266. var c = true
  267. proc shouldSink() =
  268. var x = ME(who: "me (sink)")
  269. use(x) # we analyse this
  270. if c: def(x)
  271. else: def(x)
  272. use(x) # ok, with the [else] part.
  273. shouldSink()
  274. dump = ME()
  275. proc shouldNotSink() =
  276. var x = ME(who: "me (not sink)")
  277. use(x) # we analyse this
  278. if c: def(x)
  279. use(x) # Not ok without the '[else]'
  280. shouldNotSink()
  281. # bug #14568
  282. import os
  283. type O2 = object
  284. s: seq[int]
  285. proc `=sink`(dest: var O2, src: O2) =
  286. echo "sinked and not optimized to a bitcopy"
  287. var testSeq: O2
  288. proc update() =
  289. # testSeq.add(0) # uncommenting this line fixes the leak
  290. testSeq = O2(s: @[])
  291. testSeq.s.add(0)
  292. for i in 1..3:
  293. update()
  294. # bug #14961
  295. type
  296. Foo = object
  297. data: seq[int]
  298. proc initFoo(len: int): Foo =
  299. result = (let s = newSeq[int](len); Foo(data: s) )
  300. var f = initFoo(2)
  301. echo initFoo(2)
  302. proc initFoo2(len: int) =
  303. echo if true:
  304. let s = newSeq[int](len); Foo(data: s)
  305. else:
  306. let s = newSeq[int](len); Foo(data: s)
  307. initFoo2(2)
  308. proc initFoo3(len: int) =
  309. echo (block:
  310. let s = newSeq[int](len); Foo(data: s))
  311. initFoo3(2)
  312. proc initFoo4(len: int) =
  313. echo (let s = newSeq[int](len); Foo(data: s))
  314. initFoo4(2)
  315. proc initFoo5(len: int) =
  316. echo (case true
  317. of true:
  318. let s = newSeq[int](len); Foo(data: s)
  319. of false:
  320. let s = newSeq[int](len); Foo(data: s))
  321. initFoo5(2)
  322. proc initFoo6(len: int) =
  323. echo (block:
  324. try:
  325. let s = newSeq[int](len); Foo(data: s)
  326. finally: discard)
  327. initFoo6(2)
  328. proc initFoo7(len: int) =
  329. echo (block:
  330. try:
  331. raise newException(CatchableError, "sup")
  332. let s = newSeq[int](len); Foo(data: s)
  333. except CatchableError:
  334. let s = newSeq[int](len); Foo(data: s) )
  335. initFoo7(2)
  336. # bug #14902
  337. iterator zip[T](s: openarray[T]): (T, T) =
  338. var i = 0
  339. while i < 10:
  340. yield (s[i mod 2], s[i mod 2 + 1])
  341. inc i
  342. var lastMem = int.high
  343. proc leak =
  344. const len = 10
  345. var x = @[newString(len), newString(len), newString(len)]
  346. var c = 0
  347. for (a, b) in zip(x):
  348. let newMem = getOccupiedMem()
  349. assert newMem <= lastMem
  350. lastMem = newMem
  351. c += a.len
  352. echo c
  353. leak()
  354. proc consume(a: sink string) = echo a
  355. proc weirdScopes =
  356. if (let a = "hey"; a.len > 0):
  357. echo a
  358. while (let a = "hey"; a.len > 0):
  359. echo a
  360. break
  361. var a = block: (a: "a", b: 2)
  362. echo a
  363. (discard; a) = (echo "ho"; (a: "b", b: 3))
  364. echo a
  365. var b = try: (b: "b", a: 2)
  366. except: raise
  367. echo b
  368. (discard; b) = (echo "ho"; (b: "a", a: 3))
  369. echo b
  370. var s = "break"
  371. consume((echo "hey"; s))
  372. echo s
  373. echo (block:
  374. var a = "hey"
  375. (echo "hey"; "ho"))
  376. var b2 = "ho"
  377. echo (block:
  378. var a = "hey"
  379. (echo "hey"; b2))
  380. echo b2
  381. type status = enum
  382. alive
  383. var king = "king"
  384. echo (block:
  385. var a = "a"
  386. when true:
  387. var b = "b"
  388. case alive
  389. of alive:
  390. try:
  391. var c = "c"
  392. if true:
  393. king
  394. else:
  395. "the abyss"
  396. except:
  397. echo "he ded"
  398. "dead king")
  399. echo "live long; long live"
  400. echo king
  401. weirdScopes()
  402. # bug #14985
  403. proc getScope(): string =
  404. if true:
  405. "hi"
  406. else:
  407. "else"
  408. echo getScope()
  409. proc getScope3(): string =
  410. try:
  411. "try"
  412. except:
  413. "except"
  414. echo getScope3()
  415. proc getScope2(): string =
  416. case true
  417. of true:
  418. "bye"
  419. else:
  420. "else"
  421. echo getScope2()