summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/types.nim5
-rw-r--r--compiler/vm.nim3
-rw-r--r--tests/stdlib/tmacros.nim58
3 files changed, 65 insertions, 1 deletions
diff --git a/compiler/types.nim b/compiler/types.nim
index 2c7b91d9f..7cf02c240 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1128,6 +1128,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
       a = a.skipTypes({tyDistinct, tyGenericInst})
       if a.kind != b.kind: return false
 
+  #[
+    The following code should not run in the case either side is an generic alias,
+    but it's not presently possible to distinguish the genericinsts from aliases of
+    objects ie `type A[T] = SomeObject`
+  ]#
   # this is required by tunique_type but makes no sense really:
   if tyDistinct notin {x.kind, y.kind} and x.kind == tyGenericInst and IgnoreTupleFields notin c.flags:
     let
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 1b443aff1..b64545081 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1044,7 +1044,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
                                      strictSymEquality=true))
     of opcSameNodeType:
       decodeBC(rkInt)
-      regs[ra].intVal = ord(regs[rb].node.typ.sameTypeOrNil regs[rc].node.typ)
+      regs[ra].intVal = ord(regs[rb].node.typ.sameTypeOrNil(regs[rc].node.typ, {ExactTypeDescValues, ExactGenericParams}))
+      # The types should exactly match which is why we pass `{ExactTypeDescValues..ExactGcSafety}`.
     of opcXor:
       decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].intVal != regs[rc].intVal)
diff --git a/tests/stdlib/tmacros.nim b/tests/stdlib/tmacros.nim
index 18cfdc75c..64a474743 100644
--- a/tests/stdlib/tmacros.nim
+++ b/tests/stdlib/tmacros.nim
@@ -66,3 +66,61 @@ block: # unpackVarargs
     doAssert call1(toString) == ""
     doAssert call1(toString, 10) == "10"
     doAssert call1(toString, 10, 11) == "1011"
+
+block: # SameType
+  type
+    A = int
+    B = distinct int
+    C = object
+    Generic[T, Y] = object
+  macro isSameType(a, b: typed): untyped =
+    newLit(sameType(a, b))
+
+  static:
+    assert Generic[int, int].isSameType(Generic[int, int])
+    assert Generic[A, string].isSameType(Generic[int, string])
+    assert not Generic[A, string].isSameType(Generic[B, string])
+    assert not Generic[int, string].isSameType(Generic[int, int])
+    assert isSameType(int, A)
+    assert isSameType(10, 20)
+    assert isSameType("Hello", "world")
+    assert not isSameType("Hello", cstring"world")
+    assert not isSameType(int, B)
+    assert not isSameType(int, Generic[int, int])
+    assert not isSameType(C, string)
+    assert not isSameType(C, int)
+
+
+  #[
+    # compiler sameType fails for the following, read more in `types.nim`'s `sameTypeAux`.
+    type
+      D[T] = C
+      G[T] = T
+    static:
+      assert isSameType(D[int], C)
+      assert isSameType(D[int], D[float])
+      assert isSameType(G[float](1.0), float(1.0))
+      assert isSameType(float(1.0), G[float](1.0))
+  ]#
+
+  type Tensor[T] = object
+    data: T
+
+  macro testTensorInt(x: typed): untyped =
+    let
+      tensorIntType = getTypeInst(Tensor[int])[1]
+      xTyp = x.getTypeInst
+    
+    newLit(xTyp.sameType(tensorIntType))
+
+  var
+    x: Tensor[int]
+    x1 = Tensor[float]()
+    x2 = Tensor[A]()
+    x3 = Tensor[B]()
+
+  static: 
+    assert testTensorInt(x)
+    assert not testTensorInt(x1)
+    assert testTensorInt(x2)
+    assert not testTensorInt(x3)