summary refs log tree commit diff stats
path: root/tests/generics
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2023-06-13 21:05:44 +0300
committerGitHub <noreply@github.com>2023-06-13 20:05:44 +0200
commit894a19c6ed20ecfc72ea4bda010c11371b571d45 (patch)
tree42677f9bccf28d504723550bbc3b4cc12946f90f /tests/generics
parent606e9941d0c42a361b519038dfff3af061eba381 (diff)
downloadNim-894a19c6ed20ecfc72ea4bda010c11371b571d45.tar.gz
fix calls in generic bodies, delay typecheck when no overloads match (#22029)
* sacrifice "tgenericshardcases" for working statics

* legacy switch for CI, maybe experimental later

* convert to experimental

* apparently untyped needs the experimental switch

* try special case call semcheck

* try fix

* fix compilation

* final cleanup, not experimental, make `when` work

* remove last needed use of untyped

* fix unused warning in test

* remove untyped feature
Diffstat (limited to 'tests/generics')
-rw-r--r--tests/generics/tgenerics_various.nim36
-rw-r--r--tests/generics/tuninstantiatedgenericcalls.nim72
2 files changed, 72 insertions, 36 deletions
diff --git a/tests/generics/tgenerics_various.nim b/tests/generics/tgenerics_various.nim
index 4cfa47809..aff851981 100644
--- a/tests/generics/tgenerics_various.nim
+++ b/tests/generics/tgenerics_various.nim
@@ -127,42 +127,6 @@ block trefs:
 
 
 
-block tsharedcases:
-  proc typeNameLen(x: typedesc): int {.compileTime.} =
-    result = x.name.len
-  macro selectType(a, b: typedesc): typedesc =
-    result = a
-
-  type
-    Foo[T] = object
-      data1: array[T.high, int]
-      data2: array[typeNameLen(T), float]
-      data3: array[0..T.typeNameLen, selectType(float, int)]
-    MyEnum = enum A, B, C, D
-
-  var f1: Foo[MyEnum]
-  var f2: Foo[int8]
-
-  doAssert high(f1.data1) == 2 # (D = 3) - 1 == 2
-  doAssert high(f1.data2) == 5 # (MyEnum.len = 6) - 1 == 5
-
-  doAssert high(f2.data1) == 126 # 127 - 1 == 126
-  doAssert high(f2.data2) == 3 # int8.len - 1 == 3
-
-  static:
-    doAssert high(f1.data1) == ord(C)
-    doAssert high(f1.data2) == 5 # length of MyEnum minus one, because we used T.high
-
-    doAssert high(f2.data1) == 126
-    doAssert high(f2.data2) == 3
-
-    doAssert high(f1.data3) == 6 # length of MyEnum
-    doAssert high(f2.data3) == 4 # length of int8
-
-    doAssert f2.data3[0] is float
-
-
-
 block tmap_auto:
   let x = map(@[1, 2, 3], x => x+10)
   doAssert x == @[11, 12, 13]
diff --git a/tests/generics/tuninstantiatedgenericcalls.nim b/tests/generics/tuninstantiatedgenericcalls.nim
new file mode 100644
index 000000000..c4d95a0fb
--- /dev/null
+++ b/tests/generics/tuninstantiatedgenericcalls.nim
@@ -0,0 +1,72 @@
+# Cases that used to only work due to weird workarounds in the compiler
+# involving not instantiating calls in generic bodies which are removed
+# due to breaking statics.
+# The issue was that these calls are compiled as regular expressions at
+# the generic declaration with unresolved generic parameter types,
+# which are special cased in some places in the compiler, but sometimes
+# treated like real types.
+
+block:
+  type Base10 = object
+
+  func maxLen(T: typedesc[Base10], I: type): int8 =
+    when I is uint8:
+      3
+    elif I is uint16:
+      5
+    elif I is uint32:
+      10
+    elif I is uint64:
+      20
+    else:
+      when sizeof(uint) == 4:
+        10
+      else:
+        20
+  
+  type
+    Base10Buf[T: SomeUnsignedInt] = object
+      data: array[maxLen(Base10, T), byte]
+      len: int8
+
+  var x: Base10Buf[uint32]
+  doAssert x.data.len == 10
+  var y: Base10Buf[uint16]
+  doAssert y.data.len == 5
+
+import typetraits
+
+block thardcases:
+  proc typeNameLen(x: typedesc): int {.compileTime.} =
+    result = x.name.len
+  macro selectType(a, b: typedesc): typedesc =
+    result = a
+
+  type
+    Foo[T] = object
+      data1: array[T.high, int]
+      data2: array[typeNameLen(T), float]
+      data3: array[0..T.typeNameLen, selectType(float, int)]
+  
+  type MyEnum = enum A, B, C, D
+
+  var f1: Foo[MyEnum]
+  var f2: Foo[int8]
+
+  doAssert high(f1.data1) == 2 # (D = 3) - 1 == 2
+  doAssert high(f1.data2) == 5 # (MyEnum.len = 6) - 1 == 5
+
+  doAssert high(f2.data1) == 126 # 127 - 1 == 126
+  doAssert high(f2.data2) == 3 # int8.len - 1 == 3
+
+  static:
+    doAssert high(f1.data1) == ord(C)
+    doAssert high(f1.data2) == 5 # length of MyEnum minus one, because we used T.high
+
+    doAssert high(f2.data1) == 126
+    doAssert high(f2.data2) == 3
+
+    doAssert high(f1.data3) == 6 # length of MyEnum
+    doAssert high(f2.data3) == 4 # length of int8
+
+    doAssert f2.data3[0] is float