diff options
-rw-r--r-- | compiler/types.nim | 5 | ||||
-rw-r--r-- | compiler/vm.nim | 3 | ||||
-rw-r--r-- | tests/stdlib/tmacros.nim | 58 |
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) |