Source file test/genmeth1.go

     1  // skip
     2  
     3  // Copyright 2026 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Verify that generic methods order type arguments correctly.
     8  
     9  package main
    10  
    11  import (
    12  	"fmt"
    13  	"strings"
    14  )
    15  
    16  type S[A, B any] struct {
    17  	a A
    18  	b B
    19  }
    20  
    21  func (s S[A, B]) m() string {
    22  	return typeStr(s.a, s.b)
    23  }
    24  
    25  func (s S[A, B]) n[C, D any]() string {
    26  	var c C
    27  	var d D
    28  	return typeStr(s.a, s.b, c, d)
    29  }
    30  
    31  func typeStr(args ...any) string {
    32  	s := ""
    33  	for i, arg := range args {
    34  		if i > 0 {
    35  			s += "->"
    36  		}
    37  		s += strings.TrimPrefix(fmt.Sprintf("%T", arg), "main.") // trim for brevity
    38  	}
    39  	return s
    40  }
    41  
    42  func main() {
    43  	type T1 int8
    44  	type T2 int16
    45  	type T3 int32
    46  	type T4 int64
    47  
    48  	// method calls
    49  	// static dictionary on type
    50  	check(S[T1, T2]{}.m(), "T1->T2")
    51  	check(S[T2, T1]{}.m(), "T2->T1")
    52  	// static dictionary on method
    53  	check(S[T1, T2]{}.n[T3, T4](), "T1->T2->T3->T4")
    54  	check(S[T4, T1]{}.n[T2, T3](), "T4->T1->T2->T3")
    55  	check(S[T3, T4]{}.n[T1, T2](), "T3->T4->T1->T2")
    56  	check(S[T2, T3]{}.n[T4, T1](), "T2->T3->T4->T1")
    57  	// dynamic dictionary on type
    58  	check(mCal[T1, T2](), "T1->T2")
    59  	check(mCal[T2, T1](), "T2->T1")
    60  	// dynamic dictionary on method
    61  	check(nCal[T1, T2, T3, T4](), "T1->T2->T3->T4")
    62  	check(nCal[T4, T1, T2, T3](), "T4->T1->T2->T3")
    63  	check(nCal[T3, T4, T1, T2](), "T3->T4->T1->T2")
    64  	check(nCal[T2, T3, T4, T1](), "T2->T3->T4->T1")
    65  
    66  	// method values
    67  	// static dictionary on type
    68  	mv1 := S[T1, T2]{}.m
    69  	check(mv1(), "T1->T2")
    70  	mv2 := S[T2, T1]{}.m
    71  	check(mv2(), "T2->T1")
    72  	// static dictionary on method
    73  	mv3 := S[T1, T2]{}.n[T3, T4]
    74  	check(mv3(), "T1->T2->T3->T4")
    75  	mv4 := S[T4, T1]{}.n[T2, T3]
    76  	check(mv4(), "T4->T1->T2->T3")
    77  	mv5 := S[T3, T4]{}.n[T1, T2]
    78  	check(mv5(), "T3->T4->T1->T2")
    79  	mv6 := S[T2, T3]{}.n[T4, T1]
    80  	check(mv6(), "T2->T3->T4->T1")
    81  	// dynamic dictionary on type
    82  	check(mVal[T1, T2]()(), "T1->T2")
    83  	check(mVal[T2, T1]()(), "T2->T1")
    84  	// dynamic dictionary on method
    85  	check(nVal[T1, T2, T3, T4]()(), "T1->T2->T3->T4")
    86  	check(nVal[T4, T1, T2, T3]()(), "T4->T1->T2->T3")
    87  	check(nVal[T3, T4, T1, T2]()(), "T3->T4->T1->T2")
    88  	check(nVal[T2, T3, T4, T1]()(), "T2->T3->T4->T1")
    89  
    90  	// method expressions
    91  	// static dictionary on type
    92  	me1 := S[T1, T2].m
    93  	check(me1(S[T1, T2]{}), "T1->T2")
    94  	me2 := S[T2, T1].m
    95  	check(me2(S[T2, T1]{}), "T2->T1")
    96  	// static dictionary on method
    97  	me3 := S[T1, T2].n[T3, T4]
    98  	check(me3(S[T1, T2]{}), "T1->T2->T3->T4")
    99  	me4 := S[T4, T1].n[T2, T3]
   100  	check(me4(S[T4, T1]{}), "T4->T1->T2->T3")
   101  	me5 := S[T3, T4].n[T1, T2]
   102  	check(me5(S[T3, T4]{}), "T3->T4->T1->T2")
   103  	me6 := S[T2, T3].n[T4, T1]
   104  	check(me6(S[T2, T3]{}), "T2->T3->T4->T1")
   105  	// dynamic dictionary on type
   106  	check(mExp[T1, T2]()(S[T1, T2]{}), "T1->T2")
   107  	check(mExp[T2, T1]()(S[T2, T1]{}), "T2->T1")
   108  	// dynamic dictionary on method
   109  	check(nExp[T1, T2, T3, T4]()(S[T1, T2]{}), "T1->T2->T3->T4")
   110  	check(nExp[T4, T1, T2, T3]()(S[T4, T1]{}), "T4->T1->T2->T3")
   111  	check(nExp[T3, T4, T1, T2]()(S[T3, T4]{}), "T3->T4->T1->T2")
   112  	check(nExp[T2, T3, T4, T1]()(S[T2, T3]{}), "T2->T3->T4->T1")
   113  }
   114  
   115  func check(got, want string) {
   116  	if got != want {
   117  		panic(fmt.Sprintf("got %s, want %s", got, want))
   118  	}
   119  }
   120  
   121  // piping type arguments via type parameters for dynamic dictionaries
   122  func mCal[A, B any]() string {
   123  	return S[A, B]{}.m()
   124  }
   125  
   126  func mVal[A, B any]() func() string {
   127  	return S[A, B]{}.m
   128  }
   129  
   130  func mExp[A, B any]() func(S[A, B]) string {
   131  	return S[A, B].m
   132  }
   133  
   134  func nCal[A, B, C, D any]() string {
   135  	return S[A, B]{}.n[C, D]()
   136  }
   137  
   138  func nVal[A, B, C, D any]() func() string {
   139  	return S[A, B]{}.n[C, D]
   140  }
   141  
   142  func nExp[A, B, C, D any]() func(S[A, B]) string {
   143  	return S[A, B].n[C, D]
   144  }
   145  

View as plain text