go version)?Verified on the dev.go2go branch
$ go version % bin/go version go version devel +0a030888da Sat Jun 20 04:46:40 2020 +0000 linux/amd64
Not in a release as it's on the `dev.go2go branch.
Also present in the go2go playground (currently version devel +5f01333bf1 Wed Jun 17 04:20:54 2020 +0000.)
go env)?LInux AMD64, but also the go2go playground
package main
type MapSliceConstraint(type K comparable, V interface{}) interface {
type map[K]V, []V
}
func genLen(type T MapSliceConstraint(K, V), K comparable, V interface{})(collection T) int {
return len(collection)
}
https://go2goplay.golang.org/p/1gqiYuDELuI (trimmed)
https://go2goplay.golang.org/p/qcdfl0tuHlb (with a main)
Compiling and printing:
len map: 1
len slice: 2
% go tool go2go run fim.go2
type checking failed for main
/tmp/go2go-run155966463/fim.go2:11:39: K does not satisfy comparable
(same error on either of the go2go playground links above)
func genLen(type K comparable, V interface{}, T MapSliceConstraint(K, V))(collection T) int
instead of
func genLen(type T MapSliceConstraint(K, V), K comparable, V interface{})(collection T) int
https://go2goplay.golang.org/p/zpEMFBQSep-
works correctly.
This seems to be an error in the type checker.
At the very least the error message is wrong, as K is constrained to satisfy comparable.
It's a phase-ordering issue. We know that we have several of those and fixing them will require a fairly substantial rewrite of the core of the type checker which we didn't attempt yet since this is a prototype.
(Both go/types, but also the compiler, have some of these phase-ordering issues with type-checking, due to the "eager" approach of type-checking. For regular Go, these issues mostly appear for corner-case scenarios. Unfortunately, with generics, correct phase-ordering has become paramount.)
This is another simpler case for this bug (I think): https://go2goplay.golang.org/p/6Dqyz11MnFA
func Max(type T comparable)(slice []T) T {
m := slice[0]
for i := 1; i < len(slice); i++ {
if v:= slice[i]; v > m { // ERROR: cannot compare v > m (operator > not defined for T)
m = v
}
}
return m
}
@OneOfOne The test case in https://github.com/golang/go/issues/39733#issuecomment-648876070 isn't valid: comparable permits == and !=, it doesn't permit >.
Most helpful comment
func genLen(type K comparable, V interface{}, T MapSliceConstraint(K, V))(collection T) intinstead of
func genLen(type T MapSliceConstraint(K, V), K comparable, V interface{})(collection T) inthttps://go2goplay.golang.org/p/zpEMFBQSep-
works correctly.