I'm sure this isn't surprising to you, but it was to me:
_lang
type
A = object of RootObj
B = object of A
C = object of RootObj
proc `<`[T1:A, T2](v1: T1, v2: T2): string =
return "first defn"
proc `<`[T1, T2:A](v1: T1, v2: T2): string =
return "second defn"
echo A() < 1
echo A() < C()
echo 1 < A()
produces...
bash-3.2$ nim compile --run test.nim
config/nim.cfg(53, 3) Hint: added path: '/Users/pete/.babel/pkgs/' [Path]
config/nim.cfg(54, 3) Hint: added path: '/Users/pete/.nimble/pkgs/' [Path]
Hint: used config file '/Users/pete/Downloads/nim-0.11.2/config/nim.cfg' [Conf]
Hint: system [Processing]
Hint: test [Processing]
Hint: unsigned [Processing]
test.nim(17, 7) Hint: 'foo' is declared but not used [XDeclaredButNotUsed]
test.nim(68, 8) Error: type mismatch: got (int literal(1), A)
but expected one of:
test.<(a: T, b: Slice[<.T])
test.<(v1: T1, v2: T2)
test.<(v1: T1, v2: T2)
system.<(x: ref T, y: ref T)
system.<(x: char, y: char)
system.<(x: float, y: float)
What's weird is that if I specify the first type in the second < definition, it compiles!
_lang
type
A = object of RootObj
B = object of A
C = object of RootObj
proc `<`[T1:A, T2](v1: T1, v2: T2): string =
return "first arg subtype"
proc `<`[T1:int, T2:A](v1: T1, v2: T2): string =
return "second arg subtype"
echo A() < 1
echo A() < C()
echo 1 < A()
produces...
first defn
first defn
second defn
Known behavior or bug report?
[T1, T2:A] can be interpreted as: T1 and T2 have to be of (sub)type A. And it looks like the compiler does interpret it like that.
Using [T1; T2:A] (that is ; instead of ,) in the second proc, solves that problem.
It's consistent with
var a, b: int
and
proc foo(a, b: int)
where comma binds more tightly than colon. It's unfortunate that it results in hard-to-spot errors for generic types.