This seems to work, but it's kinda dirty, and the error messages aren't great:
{.experimental.}
type
Vec2 = tuple[x, y: float]
Kinetic = concept g, type T
T.pos is Vec2
T.vel is Vec2
IKinetic = object
Box = object
pos: Vec2
vel: Vec2
converter conToInter[T: not typedesc and Kinetic](x: var T): IKinetic =
IKinetic()
template `.`(x: IKinetic, field: untyped): untyped =
123
proc dummy(k: IKinetic): IKinetic = k
var x = Box()
var y = 3
var a = dummy(x) # This is okay
var b = dummy(y) # This gives a compiler error, as it should
It avoids the infinite recursion by checking the fields on the instance type,
and excluding typedescs from the converter. I'll be happy to consider
alternatives, if there exist any.