fixes #12015 by also checking kind of typeNode (#12016)

* fixes #12015 by also checking kind of `typeNode`

If a tuple field is aliased it'll appear the same as a ref type in a
call to `getType` if only for the kind of the resulting `NimNode` is
checked (that is a `nnkBracketExpr`)

* fix test case due to #12017 and add more realistic test case

Adds an additional test case, which includes generics and is closer to
the real failure I encountered

* remove previous fix and fix differently after all

The previous fix was incomplete, because it failed for generics.

Note that the `of "tuple"` is not actually needed, the
`nnkBracketExpr` branch in the `else` branch would catch it too, but I
decided to introduce it for clarity. However, the latter is actually
needed, because it seems for aliases of `seq` we end up in it.

* update comment about global `%` proc in json test
This commit is contained in:
Vindaar
2019-08-27 22:23:47 +02:00
committed by Andreas Rumpf
parent 00d46ca1c0
commit eff0837ff4
2 changed files with 49 additions and 4 deletions

View File

@@ -1369,11 +1369,20 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
for `forLoopI` in 0 ..< `jsonNode`.len: list[`forLoopI`] =`constructorNode`;
list
)
of "tuple":
let typeNode = getTypeImpl(typeSym)
result = createConstructor(typeNode, jsonNode)
else:
# Generic type.
# Generic type or some `seq[T]` alias
let obj = getType(typeSym)
result = processType(typeSym, obj, jsonNode, false)
case obj.kind
of nnkBracketExpr:
# probably a `seq[T]` alias
let typeNode = getTypeImpl(typeSym)
result = createConstructor(typeNode, jsonNode)
else:
# generic type
result = processType(typeSym, obj, jsonNode, false)
of nnkSym:
# Handle JsonNode.
if ($typeSym).cmpIgnoreStyle("jsonnode") == 0:
@@ -1385,7 +1394,7 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
if typeNode.typeKind == ntyDistinct:
result = createConstructor(typeNode, jsonNode)
elif obj.kind == nnkBracketExpr:
# When `Sym "Foo"` turns out to be a `ref object`.
# When `Sym "Foo"` turns out to be a `ref object` or `tuple`
result = createConstructor(obj, jsonNode)
else:
result = processType(typeSym, obj, jsonNode, false)

View File

@@ -517,6 +517,42 @@ when true:
doAssert v.name == "smith"
doAssert MyRef(w).name == "smith"
# bug #12015
# The definition of the `%` proc needs to be here, since the `% c` calls below
# can only find our custom `%` proc for `Pix` if defined in global scope.
type
Pix = tuple[x, y: uint8, ch: uint16]
proc `%`(p: Pix): JsonNode =
result = %* { "x" : % p.x,
"y" : % p.y,
"ch" : % p.ch }
block:
type
Cluster = object
works: tuple[x, y: uint8, ch: uint16] # working
fails: Pix # previously broken
let data = (x: 123'u8, y: 53'u8, ch: 1231'u16)
let c = Cluster(works: data, fails: data)
let cFromJson = (% c).to(Cluster)
doAssert c == cFromJson
block:
# bug related to #12015
type
PixInt = tuple[x, y, ch: int]
SomePix = Pix | PixInt
Cluster[T: SomePix] = seq[T]
ClusterObject[T: SomePix] = object
data: Cluster[T]
RecoEvent[T: SomePix] = object
cluster: seq[ClusterObject[T]]
let data = @[(x: 123'u8, y: 53'u8, ch: 1231'u16)]
var c = RecoEvent[Pix](cluster: @[ClusterObject[Pix](data: data)])
let cFromJson = (% c).to(RecoEvent[Pix])
doAssert c == cFromJson
# TODO: when the issue with the limeted vm registers is solved, the
# exact same test as above should be evaluated at compile time as
# well, to ensure that the vm functionality won't diverge from the