tuninstantiatedgenericcalls.nim 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. # Cases that used to only work due to weird workarounds in the compiler
  2. # involving not instantiating calls in generic bodies which are removed
  3. # due to breaking statics.
  4. # The issue was that these calls are compiled as regular expressions at
  5. # the generic declaration with unresolved generic parameter types,
  6. # which are special cased in some places in the compiler, but sometimes
  7. # treated like real types.
  8. block:
  9. type Base10 = object
  10. func maxLen(T: typedesc[Base10], I: type): int8 =
  11. when I is uint8:
  12. 3
  13. elif I is uint16:
  14. 5
  15. elif I is uint32:
  16. 10
  17. elif I is uint64:
  18. 20
  19. else:
  20. when sizeof(uint) == 4:
  21. 10
  22. else:
  23. 20
  24. type
  25. Base10Buf[T: SomeUnsignedInt] = object
  26. data: array[maxLen(Base10, T), byte]
  27. len: int8
  28. var x: Base10Buf[uint32]
  29. doAssert x.data.len == 10
  30. var y: Base10Buf[uint16]
  31. doAssert y.data.len == 5
  32. import typetraits
  33. block thardcases:
  34. proc typeNameLen(x: typedesc): int {.compileTime.} =
  35. result = x.name.len
  36. macro selectType(a, b: typedesc): typedesc =
  37. result = a
  38. type
  39. Foo[T] = object
  40. data1: array[T.high, int]
  41. data2: array[typeNameLen(T), float]
  42. data3: array[0..T.typeNameLen, selectType(float, int)]
  43. type MyEnum = enum A, B, C, D
  44. var f1: Foo[MyEnum]
  45. var f2: Foo[int8]
  46. doAssert high(f1.data1) == 2 # (D = 3) - 1 == 2
  47. doAssert high(f1.data2) == 5 # (MyEnum.len = 6) - 1 == 5
  48. doAssert high(f2.data1) == 126 # 127 - 1 == 126
  49. doAssert high(f2.data2) == 3 # int8.len - 1 == 3
  50. static:
  51. doAssert high(f1.data1) == ord(C)
  52. doAssert high(f1.data2) == 5 # length of MyEnum minus one, because we used T.high
  53. doAssert high(f2.data1) == 126
  54. doAssert high(f2.data2) == 3
  55. doAssert high(f1.data3) == 6 # length of MyEnum
  56. doAssert high(f2.data3) == 4 # length of int8
  57. doAssert f2.data3[0] is float
  58. import muninstantiatedgenericcalls
  59. block:
  60. var x: Leb128Buf[uint32]
  61. doAssert x.data.len == 5
  62. var y: Leb128Buf[uint16]
  63. doAssert y.data.len == 3
  64. import macros
  65. block: # issue #12415
  66. macro isSomePointerImpl(t: typedesc): bool =
  67. var impl = t.getTypeInst[1].getTypeImpl
  68. if impl.kind == nnkDistinctTy:
  69. impl = impl[0].getTypeImpl
  70. if impl.kind in {nnkPtrTy,nnkRefTy}:
  71. result = newLit(true)
  72. elif impl.kind == nnkSym and impl.eqIdent("pointer"):
  73. result = newLit(true)
  74. else:
  75. result = newLit(false)
  76. proc isSomePointer[T](t: typedesc[T]): bool {.compileTime.} =
  77. isSomePointerImpl(t)
  78. type
  79. Option[T] = object
  80. ## An optional type that stores its value and state separately in a boolean.
  81. when isSomePointer(typedesc(T)):
  82. val: T
  83. else:
  84. val: T
  85. has: bool
  86. var x: Option[ref int]
  87. doAssert not compiles(x.has)
  88. var y: Option[int]
  89. doAssert compiles(y.has)
  90. block: # issue #2002
  91. proc isNillable(T: typedesc): bool =
  92. when compiles((let v: T = nil)):
  93. return true
  94. else:
  95. return false
  96. type
  97. Foo[T] = object
  98. when isNillable(T):
  99. nillable: float
  100. else:
  101. notnillable: int
  102. var val1: Foo[ref int]
  103. doAssert compiles(val1.nillable)
  104. doAssert not compiles(val1.notnillable)
  105. var val2: Foo[int]
  106. doAssert not compiles(val2.nillable)
  107. doAssert compiles(val2.notnillable)
  108. block: # issue #1771
  109. type
  110. Foo[X, T] = object
  111. bar: array[X.low..X.high, T]
  112. proc test[X, T](f: Foo[X, T]): T =
  113. f.bar[X.low]
  114. var a: Foo[range[0..2], float]
  115. doAssert test(a) == 0.0