mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-14 15:23:27 +00:00
Made generic type classes work with types using static parameters (#21528)
This commit is contained in:
@@ -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]
|
||||
|
||||
30
tests/metatype/tstatic_generic_typeclass.nim
Normal file
30
tests/metatype/tstatic_generic_typeclass.nim
Normal file
@@ -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 == @[]
|
||||
Reference in New Issue
Block a user