go: cmd/compile: incorrect type set intersection computation
What version of Go are you using (go version
)?
$ go version go version go1.19.4 linux/amd64
Does this issue reproduce with the latest release?
Yes, also for tip.
What did you do?
package main
func main() {}
type C1 interface {
comparable
}
type C2 interface {
comparable
[2]any | int
}
func G1[T C1](t T) {}
func G2[T C2](t T) {}
func F1[V [2]any](v V) {
_ = G1[V] // error: V does not implement comparable
}
func F2[V [2]any](v V) {
_ = G2[V] // okay (but should not?)
}
What did you expect to see?
Both F1 and F2 fail to compile.
What did you see instead?
F2 compiles okay.
My understanding is that the type set of C2 only contains int
, because [2]any
is not strictly comparable, though my understanding might be wrong.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 27 (11 by maintainers)
The type set of
C2
should just be{int}
but at the moment it is{[2]any, int}
which is incorrect (it’s the intersection of all strictly comparable types with the type set{[2]any, int}
;[2]any
is not strictly comparable and thus we should be left withint
).The intersection computation is using the wrong “comparable” predicate (not strictly comparable but “spec-comparable”). Fix forthcoming, later today.
In the first example, it is correct that
V
doesn’t implementcomparable
: the array[2]any
is not strictly comparable,V
is a type parameter, and thereforeV
does not implementcomparable
(also_ = v == v
is not permitted inF1
).I think the handling of
F2
is incorrect, this is a bug in the type checker.@go101 you’re right. I was wrong that the type set is empty, it’s actually contain
[2]any
andint
. Running gotype with tracing enabled:@go101 (from my understanding) The real constraint is
interface{[2]any}
It has to implementcomparable
but does not implement the constraint strictly comparable. (easily understood since implementation is type set inclusion)Strictly comparable
is different fromcomparable
in that it asserts that the members of its type set are themselves implementingcomparable
instead of just satisfying it. (i.e. the members of stricly comparable are themselves strictly comparable)According to my current reading of the spec at tip, strictly comparable does not matter here because
[2]any
is not an interface.[2]any
satisfies comparable because it has the comparison operators. We have type set inclusion. So the type parameter constraint you are using actually implements C2. All is fine.The compiler is correct.