From 3cdf8b429e7550c04ab986327bf9aed8de08d6fa Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 4 Aug 2021 14:25:01 -0700 Subject: [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 Reviewed-by: Keith Randall --- test/run.go | 1 - test/typeparam/mdempsky/13.go | 84 +++++++++++++++++++++++++++++++++---------- 2 files changed, 65 insertions(+), 20 deletions(-) (limited to 'test') 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) } -- cgit v1.2.3-54-g00ecf