]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: all interfaces implement comparable (add tests)
authorRobert Griesemer <gri@golang.org>
Tue, 25 Jan 2022 01:49:11 +0000 (17:49 -0800)
committerRobert Griesemer <gri@golang.org>
Tue, 25 Jan 2022 22:04:10 +0000 (22:04 +0000)
For #50646.

Change-Id: I7420545556e0df2659836364a62ce2c32ad7a8b1
Reviewed-on: https://go-review.googlesource.com/c/go/+/380654
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/issues_test.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue50646.go2 [new file with mode: 0644]
src/go/types/issues_test.go
src/go/types/testdata/fixedbugs/issue50646.go2 [new file with mode: 0644]
test/typeparam/issue50646.go [new file with mode: 0644]

index 9890b79323ac81dfe0347532b831b1cf2f635513..6b64251118c058007a830aecbbf89428c2a47f11 100644 (file)
@@ -611,3 +611,30 @@ func TestIssue43124(t *testing.T) {
                t.Errorf("type checking error for c does not disambiguate package template: %q", err)
        }
 }
+
+func TestIssue50646(t *testing.T) {
+       anyType := Universe.Lookup("any").Type()
+       comparableType := Universe.Lookup("comparable").Type()
+
+       if !Comparable(anyType) {
+               t.Errorf("any is not a comparable type")
+       }
+       if !Comparable(comparableType) {
+               t.Errorf("comparable is not a comparable type")
+       }
+
+       // TODO(gri) should comparable be an alias, like any? (see #50791)
+       if !Implements(anyType, comparableType.Underlying().(*Interface)) {
+               t.Errorf("any does not implement comparable")
+       }
+       if !Implements(comparableType, anyType.(*Interface)) {
+               t.Errorf("comparable does not implement any")
+       }
+
+       if !AssignableTo(anyType, comparableType) {
+               t.Errorf("any not assignable to comparable")
+       }
+       if !AssignableTo(comparableType, anyType) {
+               t.Errorf("comparable not assignable to any")
+       }
+}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50646.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50646.go2
new file mode 100644 (file)
index 0000000..6e8419f
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Because we can use == and != with values of arbitrary
+// interfaces, all interfaces implement comparable.
+
+func f1[_ comparable]()              {}
+func f2[_ interface{ comparable }]() {}
+
+type T interface{ m() }
+
+func _[P comparable, Q ~int, R any]() {
+       _ = f1[int]
+       _ = f1[T]
+       _ = f1[any]
+       _ = f1[P]
+       _ = f1[Q]
+       _ = f1[R /* ERROR R does not implement comparable */]
+
+       _ = f2[int]
+       _ = f2[T]
+       _ = f2[any]
+       _ = f2[P]
+       _ = f2[Q]
+       _ = f2[R /* ERROR R does not implement comparable */]
+}
index 51995af30afd39f7c174abaa1d61dfc9421277bb..613ced92ed56e8e38f5fa261fcd3197ff52d37d2 100644 (file)
@@ -638,3 +638,30 @@ var _ T = template /* ERROR cannot use.*text/template.* as T value */.Template{}
        testFiles(t, nil, []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp)
        testFiles(t, nil, []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp)
 }
+
+func TestIssue50646(t *testing.T) {
+       anyType := Universe.Lookup("any").Type()
+       comparableType := Universe.Lookup("comparable").Type()
+
+       if !Comparable(anyType) {
+               t.Errorf("any is not a comparable type")
+       }
+       if !Comparable(comparableType) {
+               t.Errorf("comparable is not a comparable type")
+       }
+
+       // TODO(gri) should comparable be an alias, like any? (see #50791)
+       if !Implements(anyType, comparableType.Underlying().(*Interface)) {
+               t.Errorf("any does not implement comparable")
+       }
+       if !Implements(comparableType, anyType.(*Interface)) {
+               t.Errorf("comparable does not implement any")
+       }
+
+       if !AssignableTo(anyType, comparableType) {
+               t.Errorf("any not assignable to comparable")
+       }
+       if !AssignableTo(comparableType, anyType) {
+               t.Errorf("comparable not assignable to any")
+       }
+}
diff --git a/src/go/types/testdata/fixedbugs/issue50646.go2 b/src/go/types/testdata/fixedbugs/issue50646.go2
new file mode 100644 (file)
index 0000000..6e8419f
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Because we can use == and != with values of arbitrary
+// interfaces, all interfaces implement comparable.
+
+func f1[_ comparable]()              {}
+func f2[_ interface{ comparable }]() {}
+
+type T interface{ m() }
+
+func _[P comparable, Q ~int, R any]() {
+       _ = f1[int]
+       _ = f1[T]
+       _ = f1[any]
+       _ = f1[P]
+       _ = f1[Q]
+       _ = f1[R /* ERROR R does not implement comparable */]
+
+       _ = f2[int]
+       _ = f2[T]
+       _ = f2[any]
+       _ = f2[P]
+       _ = f2[Q]
+       _ = f2[R /* ERROR R does not implement comparable */]
+}
diff --git a/test/typeparam/issue50646.go b/test/typeparam/issue50646.go
new file mode 100644 (file)
index 0000000..44bbe2a
--- /dev/null
@@ -0,0 +1,39 @@
+// run -gcflags=-G=3
+
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func eql[P comparable](x, y P) {
+       if x != y {
+               panic("not equal")
+       }
+}
+
+func expectPanic(f func()) {
+       defer func() {
+               if recover() == nil {
+                       panic("function succeeded unexpectedly")
+               }
+       }()
+       f()
+}
+
+func main() {
+       eql[int](1, 1)
+       eql(1, 1)
+
+       // all interfaces implement comparable
+       var x, y any = 2, 2
+       eql[any](x, y)
+       eql(x, y)
+
+       // but we may get runtime panics
+       x, y = 1, 2 // x != y
+       expectPanic(func() { eql(x, y) })
+
+       x, y = main, main // functions are not comparable
+       expectPanic(func() { eql(x, y) })
+}