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
C2should 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]anyis 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
Vdoesn’t implementcomparable: the array[2]anyis not strictly comparable,Vis a type parameter, and thereforeVdoes not implementcomparable(also_ = v == vis not permitted inF1).I think the handling of
F2is 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]anyandint. Running gotype with tracing enabled:@go101 (from my understanding) The real constraint is
interface{[2]any}It has to implementcomparablebut does not implement the constraint strictly comparable. (easily understood since implementation is type set inclusion)Strictly comparableis different fromcomparablein that it asserts that the members of its type set are themselves implementingcomparableinstead 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]anyis not an interface.[2]anysatisfies 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.