Fix VM's sametype impl to work for generics/typedescs (#19073)

* Fix vm's sametype implementation to properly handle generics and typedescs

* actually fixed sametype + have test

* added comments and removed unsafe code
This commit is contained in:
Jason Beetham
2021-11-02 02:02:53 -06:00
committed by GitHub
parent 24a7584299
commit cc984217a9
3 changed files with 65 additions and 1 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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)