aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Freeman <mark@golang.org>2026-04-08 14:10:07 -0400
committerGopher Robot <gobot@golang.org>2026-04-09 08:50:41 -0700
commit86241330242b57fd73f13014556cbd7ba4c1c1bc (patch)
tree1c26dc2f65bca1e703601ab4498cc502cd32d3bf
parent6c087a167e562242d21c702b2b66fc8329a14322 (diff)
downloadgo-86241330242b57fd73f13014556cbd7ba4c1c1bc.tar.xz
test: more tests for generic methods
These tests verify that generic method type arguments are ordered correctly for a variety of expression forms and dictionary kinds. Change-Id: I067206d1e97d5350d6fcc3983f5a6ef24a782214 Reviewed-on: https://go-review.googlesource.com/c/go/+/764200 Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Mark Freeman <markfreeman@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
-rw-r--r--test/genmeth1.go144
1 files changed, 144 insertions, 0 deletions
diff --git a/test/genmeth1.go b/test/genmeth1.go
new file mode 100644
index 0000000000..cf782a2513
--- /dev/null
+++ b/test/genmeth1.go
@@ -0,0 +1,144 @@
+//run
+
+// Copyright 2026 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.
+
+// Verify that generic methods order type arguments correctly.
+
+package main
+
+import (
+ "fmt"
+ "strings"
+)
+
+type S[A, B any] struct {
+ a A
+ b B
+}
+
+func (s S[A, B]) m() string {
+ return typeStr(s.a, s.b)
+}
+
+func (s S[A, B]) n[C, D any]() string {
+ var c C
+ var d D
+ return typeStr(s.a, s.b, c, d)
+}
+
+func typeStr(args ...any) string {
+ s := ""
+ for i, arg := range args {
+ if i > 0 {
+ s += "->"
+ }
+ s += strings.TrimPrefix(fmt.Sprintf("%T", arg), "main.") // trim for brevity
+ }
+ return s
+}
+
+func main() {
+ type T1 int8
+ type T2 int16
+ type T3 int32
+ type T4 int64
+
+ // method calls
+ // static dictionary on type
+ check(S[T1, T2]{}.m(), "T1->T2")
+ check(S[T2, T1]{}.m(), "T2->T1")
+ // static dictionary on method
+ check(S[T1, T2]{}.n[T3, T4](), "T1->T2->T3->T4")
+ check(S[T4, T1]{}.n[T2, T3](), "T4->T1->T2->T3")
+ check(S[T3, T4]{}.n[T1, T2](), "T3->T4->T1->T2")
+ check(S[T2, T3]{}.n[T4, T1](), "T2->T3->T4->T1")
+ // dynamic dictionary on type
+ check(mCal[T1, T2](), "T1->T2")
+ check(mCal[T2, T1](), "T2->T1")
+ // dynamic dictionary on method
+ check(nCal[T1, T2, T3, T4](), "T1->T2->T3->T4")
+ check(nCal[T4, T1, T2, T3](), "T4->T1->T2->T3")
+ check(nCal[T3, T4, T1, T2](), "T3->T4->T1->T2")
+ check(nCal[T2, T3, T4, T1](), "T2->T3->T4->T1")
+
+ // method values
+ // static dictionary on type
+ mv1 := S[T1, T2]{}.m
+ check(mv1(), "T1->T2")
+ mv2 := S[T2, T1]{}.m
+ check(mv2(), "T2->T1")
+ // static dictionary on method
+ mv3 := S[T1, T2]{}.n[T3, T4]
+ check(mv3(), "T1->T2->T3->T4")
+ mv4 := S[T4, T1]{}.n[T2, T3]
+ check(mv4(), "T4->T1->T2->T3")
+ mv5 := S[T3, T4]{}.n[T1, T2]
+ check(mv5(), "T3->T4->T1->T2")
+ mv6 := S[T2, T3]{}.n[T4, T1]
+ check(mv6(), "T2->T3->T4->T1")
+ // dynamic dictionary on type
+ check(mVal[T1, T2]()(), "T1->T2")
+ check(mVal[T2, T1]()(), "T2->T1")
+ // dynamic dictionary on method
+ check(nVal[T1, T2, T3, T4]()(), "T1->T2->T3->T4")
+ check(nVal[T4, T1, T2, T3]()(), "T4->T1->T2->T3")
+ check(nVal[T3, T4, T1, T2]()(), "T3->T4->T1->T2")
+ check(nVal[T2, T3, T4, T1]()(), "T2->T3->T4->T1")
+
+ // method expressions
+ // static dictionary on type
+ me1 := S[T1, T2].m
+ check(me1(S[T1, T2]{}), "T1->T2")
+ me2 := S[T2, T1].m
+ check(me2(S[T2, T1]{}), "T2->T1")
+ // static dictionary on method
+ me3 := S[T1, T2].n[T3, T4]
+ check(me3(S[T1, T2]{}), "T1->T2->T3->T4")
+ me4 := S[T4, T1].n[T2, T3]
+ check(me4(S[T4, T1]{}), "T4->T1->T2->T3")
+ me5 := S[T3, T4].n[T1, T2]
+ check(me5(S[T3, T4]{}), "T3->T4->T1->T2")
+ me6 := S[T2, T3].n[T4, T1]
+ check(me6(S[T2, T3]{}), "T2->T3->T4->T1")
+ // dynamic dictionary on type
+ check(mExp[T1, T2]()(S[T1, T2]{}), "T1->T2")
+ check(mExp[T2, T1]()(S[T2, T1]{}), "T2->T1")
+ // dynamic dictionary on method
+ check(nExp[T1, T2, T3, T4]()(S[T1, T2]{}), "T1->T2->T3->T4")
+ check(nExp[T4, T1, T2, T3]()(S[T4, T1]{}), "T4->T1->T2->T3")
+ check(nExp[T3, T4, T1, T2]()(S[T3, T4]{}), "T3->T4->T1->T2")
+ check(nExp[T2, T3, T4, T1]()(S[T2, T3]{}), "T2->T3->T4->T1")
+}
+
+func check(got, want string) {
+ if got != want {
+ panic(fmt.Sprintf("got %s, want %s", got, want))
+ }
+}
+
+// piping type arguments via type parameters for dynamic dictionaries
+func mCal[A, B any]() string {
+ return S[A, B]{}.m()
+}
+
+func mVal[A, B any]() func() string {
+ return S[A, B]{}.m
+}
+
+func mExp[A, B any]() func(S[A, B]) string {
+ return S[A, B].m
+}
+
+func nCal[A, B, C, D any]() string {
+ return S[A, B]{}.n[C, D]()
+}
+
+func nVal[A, B, C, D any]() func() string {
+ return S[A, B]{}.n[C, D]
+}
+
+func nExp[A, B, C, D any]() func(S[A, B]) string {
+ return S[A, B].n[C, D]
+}