aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2021-08-04 14:25:01 -0700
committerDan Scales <danscales@google.com>2021-08-05 17:33:41 +0000
commit3cdf8b429e7550c04ab986327bf9aed8de08d6fa (patch)
tree6684d2e1841466d33c3315e341d75539b4e63725 /test
parent1b708c0260b6627fc23dda30c3f1e691373c032d (diff)
downloadgo-3cdf8b429e7550c04ab986327bf9aed8de08d6fa.tar.gz
go-3cdf8b429e7550c04ab986327bf9aed8de08d6fa.zip
[dev.typeparams] cmd/compile: fixing case where type arg is an interface
In this case, we can't use an itab for doing a bound call, since we're converting from an interface to an interface. We do a static or dynamic type assert in new function assertToBound(). The dynamic type assert in assertToBound() is only needed if a bound is parameterized. In that case, we must do a dynamic type assert, and therefore need a dictionary entry for the type bound (see change in getGfInfo). I'm not sure if we can somehow limit this case, since using an interface as a type arg AND having the type bound of the type arg be parameterized is a very unlikely case. Had to add the TUNION case to parameterizedBy1() (which is only used for extra checking). Added a bunch of these test cases to 13.go, which now passes. Change-Id: Ic22eed637fa879b5bbb46d36b40aaad6f90b9d01 Reviewed-on: https://go-review.googlesource.com/c/go/+/339898 Trust: Dan Scales <danscales@google.com> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'test')
-rw-r--r--test/run.go1
-rw-r--r--test/typeparam/mdempsky/13.go84
2 files changed, 65 insertions, 20 deletions
diff --git a/test/run.go b/test/run.go
index 4971043ab6..6296234d56 100644
--- a/test/run.go
+++ b/test/run.go
@@ -2184,7 +2184,6 @@ var g3Failures = setOf(
"typeparam/nested.go", // -G=3 doesn't support function-local types with generics
"typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops
- "typeparam/mdempsky/13.go", // problem with interface as as a type arg.
"typeparam/mdempsky/15.go", // ICE in (*irgen).buildClosure
)
diff --git a/test/typeparam/mdempsky/13.go b/test/typeparam/mdempsky/13.go
index dc1d29bce1..b492774d3d 100644
--- a/test/typeparam/mdempsky/13.go
+++ b/test/typeparam/mdempsky/13.go
@@ -6,33 +6,79 @@
package main
-type Mer interface{ M() }
+// Interface which will be used as a regular interface type and as a type bound.
+type Mer interface{
+ M()
+}
-func F[T Mer](expectPanic bool) {
- defer func() {
- err := recover()
- if (err != nil) != expectPanic {
- print("FAIL: (", err, " != nil) != ", expectPanic, "\n")
- }
- }()
+// Interface that is a superset of Mer.
+type Mer2 interface {
+ M()
+ String() string
+}
- var t T
+func F[T Mer](t T) {
T.M(t)
+ t.M()
}
type MyMer int
func (MyMer) M() {}
+func (MyMer) String() string {
+ return "aa"
+}
+
+// Parameterized interface
+type Abs[T any] interface {
+ Abs() T
+}
+
+func G[T Abs[U], U any](t T) {
+ T.Abs(t)
+ t.Abs()
+}
+
+type MyInt int
+func (m MyInt) Abs() MyInt {
+ if m < 0 {
+ return -m
+ }
+ return m
+}
+
+type Abs2 interface {
+ Abs() MyInt
+}
+
func main() {
- F[Mer](true)
- F[struct{ Mer }](true)
- F[*struct{ Mer }](true)
-
- F[MyMer](false)
- F[*MyMer](true)
- F[struct{ MyMer }](false)
- F[struct{ *MyMer }](true)
- F[*struct{ MyMer }](true)
- F[*struct{ *MyMer }](true)
+ mm := MyMer(3)
+ ms := struct{ Mer }{Mer: mm }
+
+ // Testing F with an interface type arg: Mer and Mer2
+ F[Mer](mm)
+ F[Mer2](mm)
+ F[struct{ Mer }](ms)
+ F[*struct{ Mer }](&ms)
+
+ ms2 := struct { MyMer }{MyMer: mm}
+ ms3 := struct { *MyMer }{MyMer: &mm}
+
+ // Testing F with a concrete type arg
+ F[MyMer](mm)
+ F[*MyMer](&mm)
+ F[struct{ MyMer }](ms2)
+ F[struct{ *MyMer }](ms3)
+ F[*struct{ MyMer }](&ms2)
+ F[*struct{ *MyMer }](&ms3)
+
+ // Testing G with a concrete type args
+ mi := MyInt(-3)
+ G[MyInt,MyInt](mi)
+
+ // Interface Abs[MyInt] holding an mi.
+ intMi := Abs[MyInt](mi)
+ // First type arg here is Abs[MyInt], an interface type.
+ G[Abs[MyInt],MyInt](intMi)
}