So I ran into a funny problem today. Let me to illustrate with a contrived
example:
{.experimental.}
type
Vec2 = tuple[x, y: float]
Kinetic = concept g
g.pos is Vec2
g.vel is Vec2
IKinetic = object
converter conToInter[T: Kinetic](x: var T): IKinetic =
IKinetic()
template `.`(x: IKinetic; field: untyped): untyped =
123
conToInter(5)
This seems to throw the compiler into an infinite loop (until it gives up).
Here's my understanding of what's happening: the `conToInter` call triggers the
`Kinetic` concept checks, which use the dot operator, so the compiler tries to
find an applicable `.` implementation. In doing so, it runs into the one taking
an `IKinetic`, so now it has to check if there's an applicable conversion,
which leads it back to `conToInter`, triggering the concept checks again. The
obvious way to fix this is to avoid the dot operator inside the concept body
(which I don't mind, as it generates ugly and unhelpful errors when the checks
fail), but what should I use instead? I suppose I could search the type's AST
representation, but that seems like a slow and fragile way to do it. Are there
any alternatives?