tmovebug.nim 9.4 KB

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