t22619.nim 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. # bug #22619
  2. when false: # todo fixme
  3. block:
  4. type
  5. Resource = object
  6. value: int
  7. Object = object
  8. r {.cursor.}: Resource
  9. s {.cursor.}: seq[Resource]
  10. var numDestroy = 0
  11. proc `=copy`(x: var Resource, y: Resource) {.error.} # disallow full copies
  12. proc `=destroy`(x: Resource) =
  13. inc numDestroy
  14. proc test() =
  15. # perform the test in procedure so that globals aren't used (their different
  16. # semantics with regards to destruction would interfere)
  17. var
  18. r = Resource(value: 1) # initialize a resource
  19. s = @[Resource(value: 2)]
  20. # make sure no copy is required in the initializer expression:
  21. var o = Object(r: r, s: s)
  22. # copying the object doesn't perform a full copy of the cursor fields:
  23. var o2 = o
  24. discard addr(o2) # prevent `o2` from being turned into a cursor
  25. # check that the fields were shallow-copied:
  26. doAssert o2.r.value == 1
  27. doAssert o2.s[0].value == 2
  28. # make sure no copy is required with normal field assignments:
  29. o.r = r
  30. o.s = s
  31. # when `o` and `o2` are destroyed, their destructor must not be called on
  32. # their fields
  33. test()
  34. # one call for the `r` local and one for the object in `s`
  35. doAssert numDestroy == 2
  36. block:
  37. type Value = distinct int
  38. var numDestroy = 0
  39. when defined(gcRefc):
  40. proc `=destroy`(x: var Value) =
  41. inc numDestroy
  42. else:
  43. proc `=destroy`(x: Value) =
  44. inc numDestroy
  45. iterator iter(s: seq[Value]): int {.closure.} =
  46. # because it is used across yields, `s2` is lifted into the iterator's
  47. # environment. Since non-ref cursors in object didn't have their hooks
  48. # disabled inside the environments lifted hooks, this led to double
  49. # frees
  50. var s2 {.cursor.} = s
  51. var i = 0
  52. let L = s2.len
  53. while i < L:
  54. yield s2[i].int
  55. inc i
  56. proc test() =
  57. var s = @[Value(1), Value(2)]
  58. let cl = iter
  59. # make sure resuming the iterator works:
  60. doAssert cl(s) == 1
  61. doAssert cl(s) == 2
  62. doAssert cl(s) == 0
  63. test()
  64. doAssert numDestroy == 2