tcaseobj.nim 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. discard """
  2. valgrind: true
  3. cmd: "nim c --gc:arc -d:useMalloc $file"
  4. output: '''myobj destroyed
  5. myobj destroyed
  6. myobj destroyed
  7. A
  8. B
  9. begin
  10. end
  11. prevented
  12. (ok: true, value: "ok")
  13. @[(kind: P, pChildren: @[])]
  14. myobj destroyed
  15. '''
  16. """
  17. # bug #13102
  18. type
  19. D = ref object
  20. R = object
  21. case o: bool
  22. of false:
  23. discard
  24. of true:
  25. field: D
  26. iterator things(): R =
  27. when true:
  28. var
  29. unit = D()
  30. while true:
  31. yield R(o: true, field: unit)
  32. else:
  33. while true:
  34. var
  35. unit = D()
  36. yield R(o: true, field: unit)
  37. proc main =
  38. var i = 0
  39. for item in things():
  40. discard item.field
  41. inc i
  42. if i == 2: break
  43. main()
  44. # bug #13149
  45. type
  46. TMyObj = object
  47. p: pointer
  48. len: int
  49. proc `=destroy`(o: var TMyObj) =
  50. if o.p != nil:
  51. dealloc o.p
  52. o.p = nil
  53. echo "myobj destroyed"
  54. proc `=copy`(dst: var TMyObj, src: TMyObj) =
  55. `=destroy`(dst)
  56. dst.p = alloc(src.len)
  57. dst.len = src.len
  58. proc `=sink`(dst: var TMyObj, src: TMyObj) =
  59. `=destroy`(dst)
  60. dst.p = src.p
  61. dst.len = src.len
  62. type
  63. TObjKind = enum Z, A, B
  64. TCaseObj = object
  65. case kind: TObjKind
  66. of Z: discard
  67. of A:
  68. x1: int # this int plays important role
  69. x2: TMyObj
  70. of B:
  71. y: TMyObj
  72. proc testSinks: TCaseObj =
  73. result = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5)))
  74. result = TCaseObj(kind: B, y: TMyObj(len: 3, p: alloc(3)))
  75. proc use(x: TCaseObj) = discard
  76. proc testCopies(i: int) =
  77. var a: array[2, TCaseObj]
  78. a[i] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5)))
  79. a[i+1] = a[i] # copy, cannot move
  80. use(a[i])
  81. let x1 = testSinks()
  82. testCopies(0)
  83. # bug #12957
  84. type
  85. PegKind* = enum
  86. pkCharChoice,
  87. pkSequence
  88. Peg* = object ## type that represents a PEG
  89. case kind: PegKind
  90. of pkCharChoice: charChoice: ref set[char]
  91. else: discard
  92. sons: seq[Peg]
  93. proc charSet*(s: set[char]): Peg =
  94. ## constructs a PEG from a character set `s`
  95. result = Peg(kind: pkCharChoice)
  96. new(result.charChoice)
  97. result.charChoice[] = s
  98. proc len(a: Peg): int {.inline.} = return a.sons.len
  99. proc myadd(d: var Peg, s: Peg) {.inline.} = add(d.sons, s)
  100. proc sequence*(a: openArray[Peg]): Peg =
  101. result = Peg(kind: pkSequence, sons: @[])
  102. when false:
  103. #works too:
  104. result.myadd(a[0])
  105. result.myadd(a[1])
  106. for x in items(a):
  107. # works:
  108. #result.sons.add(x)
  109. # fails:
  110. result.myadd x
  111. if result.len == 1:
  112. result = result.sons[0] # this must not move!
  113. when true:
  114. # bug #12957
  115. proc p =
  116. echo "A"
  117. let x = sequence([charSet({'a'..'z', 'A'..'Z', '_'}),
  118. charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'})])
  119. echo "B"
  120. p()
  121. proc testSubObjAssignment =
  122. echo "begin"
  123. # There must be extactly one element in the array constructor!
  124. let x = sequence([charSet({'a'..'z', 'A'..'Z', '_'})])
  125. echo "end"
  126. testSubObjAssignment()
  127. #------------------------------------------------
  128. type
  129. MyObject = object
  130. x1: string
  131. case kind1: bool
  132. of false: y1: string
  133. of true:
  134. y2: seq[string]
  135. case kind2: bool
  136. of true: z1: string
  137. of false:
  138. z2: seq[string]
  139. flag: bool
  140. x2: string
  141. proc test_myobject =
  142. var x: MyObject = MyObject()
  143. x.x1 = "x1"
  144. x.x2 = "x2"
  145. x.y1 = "ljhkjhkjh"
  146. {.cast(uncheckedAssign).}:
  147. x.kind1 = true
  148. x.y2 = @["1", "2"]
  149. {.cast(uncheckedAssign).}:
  150. x.kind2 = true
  151. x.z1 = "yes"
  152. {.cast(uncheckedAssign).}:
  153. x.kind2 = false
  154. x.z2 = @["1", "2"]
  155. {.cast(uncheckedAssign).}:
  156. x.kind2 = true
  157. x.z1 = "yes"
  158. x.kind2 = true # should be no effect
  159. doAssert(x.z1 == "yes")
  160. {.cast(uncheckedAssign).}:
  161. x.kind2 = false
  162. {.cast(uncheckedAssign).}:
  163. x.kind1 = x.kind2 # support self assignment with effect
  164. try:
  165. x.kind1 = x.flag # flag is not accesible
  166. except FieldDefect:
  167. echo "prevented"
  168. doAssert(x.x1 == "x1")
  169. doAssert(x.x2 == "x2")
  170. test_myobject()
  171. #------------------------------------------------
  172. # bug #14244
  173. type
  174. RocksDBResult*[T] = object
  175. case ok*: bool
  176. of true:
  177. value*: T
  178. else:
  179. error*: string
  180. proc init(): RocksDBResult[string] =
  181. result = default(RocksDBResult[string])
  182. {.cast(uncheckedAssign).}:
  183. result.ok = true
  184. result.value = "ok"
  185. echo init()
  186. #------------------------------------------------
  187. # bug #14312
  188. type MyObj = object
  189. case kind: bool
  190. of false: x0: int # would work with a type like seq[int]; value would be reset
  191. of true: x1: string
  192. var a = MyObj(kind: false, x0: 1234)
  193. {.cast(uncheckedAssign).}:
  194. a.kind = true
  195. doAssert(a.x1 == "")
  196. block:
  197. # bug #15532
  198. type Kind = enum
  199. k0, k1
  200. type Foo = object
  201. y: int
  202. case kind: Kind
  203. of k0: x0: int
  204. of k1: x1: int
  205. const j0 = Foo(y: 1, kind: k0, x0: 2)
  206. const j1 = Foo(y: 1, kind: k1, x1: 2)
  207. doAssert j0.y == 1
  208. doAssert j0.kind == k0
  209. doAssert j1.kind == k1
  210. doAssert j1.x1 == 2
  211. doAssert j0.x0 == 2
  212. # ------------------------------------
  213. # bug #20305
  214. type
  215. ContentNodeKind = enum
  216. P, Br, Text
  217. ContentNode = object
  218. case kind: ContentNodeKind
  219. of P: pChildren: seq[ContentNode]
  220. of Br: discard
  221. of Text: textStr: string
  222. proc bug20305 =
  223. var x = ContentNode(kind: P, pChildren: @[
  224. ContentNode(kind: P, pChildren: @[ContentNode(kind: Text, textStr: "brrr")])
  225. ])
  226. x.pChildren.add ContentNode(kind: Br)
  227. x.pChildren.del(0)
  228. {.cast(uncheckedAssign).}:
  229. x.pChildren[0].kind = P
  230. echo x.pChildren
  231. bug20305()
  232. # bug #21023
  233. block:
  234. block:
  235. type
  236. MGErrorKind = enum
  237. mgeUnexpected, mgeNotFound
  238. type Foo = object
  239. kind: MGErrorKind
  240. ex: Exception
  241. type Boo = object
  242. a: seq[int]
  243. type
  244. Result2 = object
  245. case o: bool
  246. of false:
  247. e: Foo
  248. of true:
  249. v: Boo
  250. proc startSessionSync(): Result2 =
  251. return Result2(o: true)
  252. proc mainSync =
  253. let ff = startSessionSync()
  254. doAssert ff.o == true
  255. mainSync()
  256. block:
  257. type
  258. MGErrorKind = enum
  259. mgeUnexpected, mgeNotFound
  260. type Foo = object
  261. kind: MGErrorKind
  262. ex: Exception
  263. type Boo = object
  264. a: seq[int]
  265. type
  266. Result2 = object
  267. case o: bool
  268. of false:
  269. e: Foo
  270. of true:
  271. v: Boo
  272. s: int
  273. proc startSessionSync(): Result2 =
  274. return Result2(o: true, s: 12)
  275. proc mainSync =
  276. let ff = startSessionSync()
  277. doAssert ff.s == 12
  278. mainSync()
  279. import std/sequtils
  280. # bug #23690
  281. type
  282. SomeObj* = object of RootObj
  283. Item* = object
  284. case kind*: 0..1
  285. of 0:
  286. a*: int
  287. b*: SomeObj
  288. of 1:
  289. c*: string
  290. ItemExt* = object
  291. a*: Item
  292. b*: string
  293. proc do1(x: int): seq[(string, Item)] =
  294. result = @[("zero", Item(kind: 1, c: "first"))]
  295. proc do2(x: int, e: ItemExt): seq[(string, ItemExt)] =
  296. do1(x).map(proc(v: (string, Item)): auto = (v[0], ItemExt(a: v[1], b: e.b)))
  297. doAssert $do2(0, ItemExt(a: Item(kind: 1, c: "second"), b: "third")) == """@[("zero", (a: (kind: 1, c: "first"), b: "third"))]"""