mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-18 02:27:10 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user