diff options
-rw-r--r-- | compiler/semtypinst.nim | 27 | ||||
-rw-r--r-- | tests/metatype/tstatic_generic_typeclass.nim | 30 |
2 files changed, 53 insertions, 4 deletions
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 0a0ac1704..0ef1d0898 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -193,6 +193,24 @@ proc replaceObjBranches(cl: TReplTypeVars, n: PNode): PNode = for i in 0..<n.len: n[i] = replaceObjBranches(cl, n[i]) +proc hasValuelessStatics(n: PNode): bool = + # We should only attempt to call an expression that has no tyStatics + # As those are unresolved generic parameters, which means in the following + # The compiler attempts to do `T == 300` which errors since the typeclass `MyThing` lacks a parameter + #[ + type MyThing[T: static int] = object + when T == 300: + a + proc doThing(_: MyThing) + ]# + if n.safeLen == 0: + n.typ.kind == tyStatic + else: + for x in n: + if hasValuelessStatics(x): + return true + false + proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode = if n == nil: return result = copyNode(n) @@ -217,10 +235,11 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode = of nkElifBranch: checkSonsLen(it, 2, cl.c.config) var cond = prepareNode(cl, it[0]) - var e = cl.c.semConstExpr(cl.c, cond) - if e.kind != nkIntLit: - internalError(cl.c.config, e.info, "ReplaceTypeVarsN: when condition not a bool") - if e.intVal != 0 and branch == nil: branch = it[1] + if not cond.hasValuelessStatics: + var e = cl.c.semConstExpr(cl.c, cond) + if e.kind != nkIntLit: + internalError(cl.c.config, e.info, "ReplaceTypeVarsN: when condition not a bool") + if e.intVal != 0 and branch == nil: branch = it[1] of nkElse: checkSonsLen(it, 1, cl.c.config) if branch == nil: branch = it[0] diff --git a/tests/metatype/tstatic_generic_typeclass.nim b/tests/metatype/tstatic_generic_typeclass.nim new file mode 100644 index 000000000..0e9256a62 --- /dev/null +++ b/tests/metatype/tstatic_generic_typeclass.nim @@ -0,0 +1,30 @@ +type MyThing[T: static int] = object + when T == 300: + a: int + +var a = MyThing[300]() +proc doThing(myThing: MyThing): string = $myThing +proc doOtherThing[T](myThing: MyThing[T]): string = $myThing +assert doThing(a) == $a +assert doThing(MyThing[0]()) == $MyThing[0]() +assert doOtherThing(a) == "(a: 0)" + +type + Backend* = enum + Cpu, + Cuda + + Tensor*[B: static[Backend]; T] = object + shape: seq[int] + strides: seq[int] + offset: int + when B == Backend.Cpu: + data: seq[T] + else: + data_ptr: ptr T + +template shape*(t: Tensor): seq[int] = + t.shape + + +assert Tensor[Cpu, int]().shape == @[] |