github.com/goplus/gogen@v1.16.0/typeparams_test.go (about)

     1  /*
     2   Copyright 2022 The GoPlus Authors (goplus.org)
     3   Licensed under the Apache License, Version 2.0 (the "License");
     4   you may not use this file except in compliance with the License.
     5   You may obtain a copy of the License at
     6       http://www.apache.org/licenses/LICENSE-2.0
     7   Unless required by applicable law or agreed to in writing, software
     8   distributed under the License is distributed on an "AS IS" BASIS,
     9   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10   See the License for the specific language governing permissions and
    11   limitations under the License.
    12  */
    13  
    14  package gogen_test
    15  
    16  import (
    17  	"go/token"
    18  	"go/types"
    19  	"log"
    20  	"runtime"
    21  	"testing"
    22  
    23  	"github.com/goplus/gogen"
    24  	"github.com/goplus/gogen/internal/goxdbg"
    25  )
    26  
    27  func TestMethodToFunc(t *testing.T) {
    28  	const src = `package hello
    29  
    30  type Itf interface {
    31  	X()
    32  }
    33  
    34  type Base struct {
    35  }
    36  
    37  func (p Base) F() {}
    38  
    39  func (p *Base) PtrF() {}
    40  
    41  type Foo struct {
    42  	Itf
    43  	Base
    44  	Val byte
    45  }
    46  
    47  func (a Foo) Bar() int {
    48  	return 0
    49  }
    50  
    51  func (a *Foo) PtrBar() string {
    52  	return ""
    53  }
    54  
    55  var _ = (Foo).Bar
    56  var _ = (*Foo).PtrBar
    57  var _ = (Foo).F
    58  var _ = (*Foo).PtrF
    59  var _ = (Foo).X
    60  var _ = (*Foo).X
    61  var _ = (Itf).X
    62  `
    63  	gt := newGoxTest()
    64  	_, err := gt.LoadGoPackage("hello", "foo.go", src)
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	pkg := gt.NewPackage("", "main")
    69  	pkgRef := pkg.Import("hello")
    70  	objFoo := pkgRef.Ref("Foo")
    71  	objItf := pkgRef.Ref("Itf")
    72  	typ := objFoo.Type()
    73  	typItf := objItf.Type()
    74  	_, err = pkg.MethodToFunc(typ, "Val")
    75  	if err == nil || err.Error() != "-:  undefined (type hello.Foo has no method Val)" {
    76  		t.Fatal("MethodToFunc failed:", err)
    77  	}
    78  	checkMethodToFunc(t, pkg, typ, "Bar", "(hello.Foo).Bar")
    79  	checkMethodToFunc(t, pkg, types.NewPointer(typ), "PtrBar", "(*hello.Foo).PtrBar")
    80  	checkMethodToFunc(t, pkg, typ, "PtrBar", "(*hello.Foo).PtrBar")
    81  	checkMethodToFunc(t, pkg, typ, "F", "(hello.Foo).F")
    82  	checkMethodToFunc(t, pkg, types.NewPointer(typ), "PtrF", "(*hello.Foo).PtrF")
    83  	checkMethodToFunc(t, pkg, typ, "PtrF", "(*hello.Foo).PtrF")
    84  	checkMethodToFunc(t, pkg, typItf, "X", "(hello.Itf).X")
    85  	checkMethodToFunc(t, pkg, typ, "X", "(hello.Foo).X")
    86  	checkMethodToFunc(t, pkg, types.NewPointer(typ), "X", "(*hello.Foo).X")
    87  }
    88  
    89  func checkMethodToFunc(t *testing.T, pkg *gogen.Package, typ types.Type, name, code string) {
    90  	t.Helper()
    91  	ret, err := pkg.MethodToFunc(typ, name)
    92  	if err != nil {
    93  		t.Fatal("MethodToFunc failed:", err)
    94  	}
    95  	if _, isPtr := typ.(*types.Pointer); isPtr {
    96  		if recv := ret.Type.(*types.Signature).Params().At(0); !types.Identical(recv.Type(), typ) {
    97  			t.Fatalf("MethodToFunc: ResultType: %v, Expected: %v\n", recv.Type(), typ)
    98  		}
    99  	}
   100  	if v := goxdbg.Format(pkg.Fset, ret.Val); v != code {
   101  		t.Fatalf("MethodToFunc:\nResult:\n%s\nExpected:\n%s\n", v, code)
   102  	}
   103  }
   104  
   105  func TestTypeAsParamsFunc(t *testing.T) {
   106  	const src = `package foo
   107  
   108  const GopPackage = true
   109  
   110  type basetype interface {
   111  	int | string
   112  }
   113  
   114  func Gopx_Bar[T basetype](name string) {
   115  }
   116  
   117  func Gopx_Row__0[T basetype](name string) {
   118  }
   119  
   120  func Gopx_Row__1[Array any](v int) {
   121  }
   122  
   123  type Table struct {
   124  }
   125  
   126  func Gopt_Table_Gopx_Col__0[T basetype](p *Table, name string) {
   127  }
   128  
   129  func Gopt_Table_Gopx_Col__1[Array any](p *Table, v int) {
   130  }
   131  `
   132  	gt := newGoxTest()
   133  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   134  	if err != nil {
   135  		t.Fatal(err)
   136  	}
   137  	pkg := gt.NewPackage("", "test")
   138  	foo := pkg.Import("foo")
   139  	objTable := foo.Ref("Table")
   140  	typ := objTable.Type().(*types.Named)
   141  	tyInt := types.Typ[types.Int]
   142  
   143  	cb := pkg.NewFunc(nil, "Example", nil, nil, false).BodyStart(pkg).
   144  		NewVar(types.NewPointer(typ), "tbl")
   145  	_, err = cb.VarVal("tbl").Member("col", gogen.MemberFlagMethodAlias)
   146  	if err != nil {
   147  		t.Fatal("tbl.Member(col):", err)
   148  	}
   149  	cb.Typ(tyInt).Val("bar").Call(2).EndStmt().
   150  		Val(foo.Ref("Bar")).Typ(tyInt).Val("1").Call(2).EndStmt().
   151  		Val(foo.Ref("Row")).Typ(tyInt).Val(1, source("1")).Call(2).EndStmt().
   152  		End()
   153  
   154  	domTest(t, pkg, `package test
   155  
   156  import "foo"
   157  
   158  func Example() {
   159  	var tbl *foo.Table
   160  	foo.Gopt_Table_Gopx_Col__0[int](tbl, "bar")
   161  	foo.Gopx_Bar[int]("1")
   162  	foo.Gopx_Row__1[int](1)
   163  }
   164  `)
   165  }
   166  
   167  func TestCheckGopPkg(t *testing.T) {
   168  	const src = `package foo
   169  
   170  import "io"
   171  
   172  const GopPackage = "io"
   173  
   174  type basetype interface {
   175  	int | string
   176  }
   177  
   178  func Gopx_Bar[T basetype](name string) {
   179  }
   180  
   181  func Gopx_Row__0[T basetype](name string) {
   182  }
   183  
   184  func Gopx_Row__1[Array any](v int) {
   185  }
   186  
   187  type EmbIntf interface {
   188  	io.Reader
   189  	Close()
   190  }
   191  
   192  type Table struct {
   193  	EmbIntf
   194  	N int
   195  	b string
   196  }
   197  
   198  func Gopt_Table_Gopx_Col__0[T basetype](p *Table, name string) {
   199  }
   200  
   201  func Gopt_Table_Gopx_Col__1[Array any](p *Table, v int) {
   202  }
   203  `
   204  	gt := newGoxTest()
   205  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   206  	if err != nil {
   207  		t.Fatal(err)
   208  	}
   209  	pkg := gt.NewPackage("", "test")
   210  	foo := pkg.Import("foo")
   211  	objTable := foo.Ref("Table")
   212  	typ := objTable.Type().(*types.Named)
   213  	tyInt := types.Typ[types.Int]
   214  
   215  	typSlice := types.NewSlice(types.NewPointer(typ))
   216  	typMap := types.NewMap(types.Typ[types.String], typSlice)
   217  
   218  	args := types.NewTuple(types.NewParam(0, pkg.Types, "tbls", typMap))
   219  	cb := pkg.NewFunc(nil, "Example", args, nil, false).BodyStart(pkg)
   220  	_, err = cb.VarVal("tbls").Val("Hi").Index(1, false).Val(0).Index(1, false).Member("col", gogen.MemberFlagMethodAlias)
   221  	if err != nil {
   222  		t.Fatal("tbl.Member(col):", err)
   223  	}
   224  	cb.Typ(tyInt).Val("bar").Call(2).EndStmt().
   225  		Val(foo.Ref("Bar")).Typ(tyInt).Val("1").Call(2).EndStmt().
   226  		Val(foo.Ref("Row")).Typ(tyInt).Val(1, source("1")).Call(2).EndStmt().
   227  		End()
   228  
   229  	typChan := types.NewChan(types.SendRecv, typSlice)
   230  	typArray := types.NewArray(typChan, 2)
   231  	args = types.NewTuple(types.NewParam(0, pkg.Types, "", typArray))
   232  	pkg.NewFunc(nil, "Create", args, nil, false).BodyStart(pkg).End()
   233  
   234  	domTest(t, pkg, `package test
   235  
   236  import "foo"
   237  
   238  const GopPackage = "foo"
   239  
   240  func Example(tbls map[string][]*foo.Table) {
   241  	foo.Gopt_Table_Gopx_Col__0[int](tbls["Hi"][0], "bar")
   242  	foo.Gopx_Bar[int]("1")
   243  	foo.Gopx_Row__1[int](1)
   244  }
   245  func Create([2]chan []*foo.Table) {
   246  }
   247  `)
   248  }
   249  
   250  func TestOverloadNamed(t *testing.T) {
   251  	const src = `package foo
   252  
   253  const GopPackage = true
   254  
   255  type M = map[string]any
   256  
   257  type basetype interface {
   258  	string | int | bool | float64
   259  }
   260  
   261  type Var__0[T basetype] struct {
   262  	val T
   263  }
   264  
   265  type Var__1[T map[string]any] struct {
   266  	val T
   267  }
   268  
   269  func Gopx_Var_Cast__0[T basetype]() *Var__0[T] {
   270  	return new(Var__0[T])
   271  }
   272  
   273  func Gopx_Var_Cast__1[T map[string]any]() *Var__1[T] {
   274  	return new(Var__1[T])
   275  }
   276  `
   277  	gt := newGoxTest()
   278  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   279  	if err != nil {
   280  		t.Fatal(err)
   281  	}
   282  	pkg := gt.NewPackage("", "main")
   283  	pkgRef := pkg.Import("foo")
   284  	scope := pkgRef.Types.Scope()
   285  	log.Println("==> Lookup", scope.Lookup("Var__0"))
   286  	objVar := pkgRef.Ref("Var")
   287  	typ := objVar.Type()
   288  	on, ok := gogen.CheckOverloadNamed(typ)
   289  	if !ok {
   290  		t.Fatal("TestOverloadNamed: not TyOverloadNamed?")
   291  	}
   292  	if on.Types[0].TypeParams() == nil {
   293  		t.Fatal("TestOverloadNamed: not generic")
   294  	}
   295  
   296  	tyInt := types.Typ[types.Int]
   297  	tyM := pkgRef.Ref("M").Type()
   298  	ty1 := pkg.Instantiate(typ, []types.Type{tyInt})
   299  	ty2 := pkg.Instantiate(typ, []types.Type{tyM})
   300  	pkg.NewTypeDefs().NewType("t1").InitType(pkg, ty1)
   301  	pkg.NewTypeDefs().NewType("t2").InitType(pkg, ty2)
   302  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   303  		Val(objVar).Typ(tyInt).Call(1).EndStmt().
   304  		Val(objVar).Typ(tyM).Call(1).EndStmt().
   305  		End()
   306  
   307  	domTest(t, pkg, `package main
   308  
   309  import "foo"
   310  
   311  type t1 foo.Var__0[int]
   312  type t2 foo.Var__1[map[string]any]
   313  
   314  func main() {
   315  	foo.Gopx_Var_Cast__0[int]()
   316  	foo.Gopx_Var_Cast__1[map[string]any]()
   317  }
   318  `)
   319  
   320  	func() {
   321  		defer func() {
   322  			if e := recover(); e == nil {
   323  				t.Fatal("TestOverloadNamed failed: no error?")
   324  			}
   325  		}()
   326  		ty3 := pkg.Instantiate(on, []types.Type{gogen.TyByte})
   327  		pkg.NewTypeDefs().NewType("t3").InitType(pkg, ty3)
   328  	}()
   329  	func() {
   330  		defer func() {
   331  			if e := recover(); e != nil && e.(error).Error() != "-: 1 (type untyped int) is not a type" {
   332  				t.Fatal("TestOverloadNamed failed:", e)
   333  			}
   334  		}()
   335  		pkg.NewFunc(nil, "bar", nil, nil, false).BodyStart(pkg).
   336  			Val(objVar).Val(1, source("1")).Call(1).EndStmt().
   337  			End()
   338  	}()
   339  }
   340  
   341  func TestInstantiate(t *testing.T) {
   342  	const src = `package foo
   343  
   344  type Data[T any] struct {
   345  	v T
   346  }
   347  
   348  type sliceOf[E any] interface {
   349  	~[]E
   350  }
   351  
   352  type Slice[S sliceOf[T], T any] struct {
   353  	Data S
   354  }
   355  
   356  func (p *Slice[S, T]) Append(t ...T) S {
   357  	p.Data = append(p.Data, t...)
   358  	return p.Data
   359  }
   360  
   361  type (
   362  	DataInt = Data[int]
   363  	SliceInt = Slice[[]int,int]
   364  )
   365  `
   366  	gt := newGoxTest()
   367  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   368  	if err != nil {
   369  		t.Fatal(err)
   370  	}
   371  	pkg := gt.NewPackage("", "main")
   372  	pkgRef := pkg.Import("foo")
   373  	tyData := pkgRef.Ref("Data").Type()
   374  	tyInt := types.Typ[types.Int]
   375  	tyInvalid := types.Typ[types.Invalid]
   376  	tySlice := pkgRef.Ref("Slice").Type()
   377  	if ret := pkg.Instantiate(tyData, []types.Type{tyInt}); ret == tyInvalid {
   378  		t.Fatal("TestInstantiate failed: pkg.Instantiate")
   379  	}
   380  	func() {
   381  		defer func() {
   382  			if e := recover(); e.(error).Error() != "-: int is not a generic type" {
   383  				t.Fatal("TestInstantiate failed:", e)
   384  			}
   385  		}()
   386  		pkg.Instantiate(tyInt, nil)
   387  	}()
   388  	func() {
   389  		defer func() {
   390  			if e := recover(); e == nil {
   391  				t.Fatal("TestInstantiate failed: no error?")
   392  			}
   393  		}()
   394  		pkg.Instantiate(tySlice, []types.Type{tyInt})
   395  	}()
   396  }
   397  
   398  func TestTypeParamsType(t *testing.T) {
   399  	const src = `package foo
   400  
   401  type Data[T any] struct {
   402  	v T
   403  }
   404  
   405  type sliceOf[E any] interface {
   406  	~[]E
   407  }
   408  
   409  type Slice[S sliceOf[T], T any] struct {
   410  	Data S
   411  }
   412  
   413  func (p *Slice[S, T]) Append(t ...T) S {
   414  	p.Data = append(p.Data, t...)
   415  	return p.Data
   416  }
   417  
   418  type (
   419  	DataInt = Data[int]
   420  	SliceInt = Slice[[]int,int]
   421  )
   422  `
   423  	gt := newGoxTest()
   424  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   425  	if err != nil {
   426  		t.Fatal(err)
   427  	}
   428  	pkg := gt.NewPackage("", "main")
   429  	pkgRef := pkg.Import("foo")
   430  	tySlice := pkgRef.Ref("Slice").Type()
   431  	tySliceInt := pkgRef.Ref("SliceInt").Type()
   432  	tyData := pkgRef.Ref("Data").Type()
   433  	tyDataInt := pkgRef.Ref("DataInt").Type()
   434  	tyInt := types.Typ[types.Int]
   435  	tyIntSlice := types.NewSlice(tyInt)
   436  
   437  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   438  		NewVarStart(types.NewPointer(tyDataInt), "data").Typ(tyData).Typ(tyInt).Index(1, false).Star().Val(nil).Call(1).EndInit(1).
   439  		NewVarStart(types.NewPointer(tySliceInt), "slice").Typ(tySlice).Typ(tyIntSlice).Typ(tyInt).Index(2, false).Star().Val(nil).Call(1).EndInit(1).
   440  		End()
   441  	domTest(t, pkg, `package main
   442  
   443  import "foo"
   444  
   445  func main() {
   446  	var data *foo.Data[int] = (*foo.Data[int])(nil)
   447  	var slice *foo.Slice[[]int, int] = (*foo.Slice[[]int, int])(nil)
   448  }
   449  `)
   450  }
   451  
   452  func TestTypeParamsFunc(t *testing.T) {
   453  	const src = `package foo
   454  
   455  type Number interface {
   456  	~int | float64
   457  }
   458  
   459  func Sum[T Number](vec []T) T {
   460  	var sum T
   461  	for _, elt := range vec {
   462  		sum = sum + elt
   463  	}
   464  	return sum
   465  }
   466  
   467  func At[T interface{ ~[]E }, E any](x T, i int) E {
   468  	return x[i]
   469  }
   470  
   471  func Loader[T1 any, T2 any](p1 T1, p2 T2) T1 {
   472  	return p1
   473  }
   474  
   475  func Add[T1 any, T2 ~int](v1 T1, v2 ...T2) (sum T2) {
   476  	println(v1)
   477  	for _, v := range v2 {
   478  		sum += v
   479  	}
   480  	return sum
   481  }
   482  
   483  type Int []int
   484  var MyInts = Int{1,2,3,4}
   485  `
   486  	gt := newGoxTest()
   487  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   488  	if err != nil {
   489  		t.Fatal(err)
   490  	}
   491  	pkg := gt.NewPackage("", "main")
   492  	pkgRef := pkg.Import("foo")
   493  	fnSum := pkgRef.Ref("Sum")
   494  	fnAt := pkgRef.Ref("At")
   495  	fnLoader := pkgRef.Ref("Loader")
   496  	fnAdd := pkgRef.Ref("Add")
   497  	myInts := pkgRef.Ref("MyInts")
   498  	tyInt := types.Typ[types.Int]
   499  	tyString := types.Typ[types.String]
   500  	tyIntSlice := types.NewSlice(tyInt)
   501  	tyIntPointer := types.NewPointer(tyInt)
   502  	var fn1 *types.Var
   503  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   504  		VarRef(nil).Val(fnAt).Typ(tyIntSlice).Index(1, false).Assign(1, 1).
   505  		VarRef(nil).Val(fnSum).Typ(tyInt).Index(1, false).Assign(1, 1).
   506  		VarRef(nil).Val(fnLoader).Typ(tyInt).Typ(tyInt).Index(2, false).Assign(1, 1).
   507  		VarRef(nil).Val(fnAdd).Typ(tyString).Typ(tyInt).Index(2, false).Assign(1, 1).
   508  		NewVarStart(tyInt, "s1").Val(fnSum).Val(1).Val(2).Val(3).SliceLit(tyIntSlice, 3).Call(1).EndInit(1).
   509  		NewVarStart(tyInt, "s2").Val(fnSum).Typ(tyInt).Index(1, false).Val(1).Val(2).Val(3).SliceLit(tyIntSlice, 3).Call(1).EndInit(1).
   510  		NewVarStart(tyInt, "v1").Val(fnAt).Val(1).Val(2).Val(3).SliceLit(tyIntSlice, 3).Val(1).Call(2).EndInit(1).
   511  		NewVarStart(tyInt, "v2").Val(fnAt).Typ(tyIntSlice).Index(1, false).Val(1).Val(2).Val(3).SliceLit(tyIntSlice, 3).Val(1).Call(2).EndInit(1).
   512  		NewVarStart(tyInt, "v3").Val(fnAt).Typ(tyIntSlice).Typ(tyInt).Index(2, false).Val(1).Val(2).Val(3).SliceLit(tyIntSlice, 3).Val(1).Call(2).EndInit(1).
   513  		NewVarStart(tyInt, "n1").Val(fnAdd).Val("hello").Val(1).Val(2).Val(3).Call(4).EndInit(1).
   514  		NewVarStart(tyInt, "n2").Val(fnAdd).Typ(tyString).Index(1, false).Val("hello").Val(1).Val(2).Val(3).Call(4).EndInit(1).
   515  		NewVarStart(tyInt, "n3").Val(fnAdd).Typ(tyString).Typ(tyInt).Index(2, false).Val("hello").Val(1).Val(2).Val(3).Call(4).EndInit(1).
   516  		NewVarStart(tyInt, "n4").Val(fnAdd).Val("hello").Val(1).Val(2).Val(3).SliceLit(tyIntSlice, 3).CallWith(2, gogen.InstrFlagEllipsis).EndInit(1).
   517  		NewVarStart(tyInt, "n5").Val(fnAdd).Val("hello").Val(1).Val(2).Val(3).SliceLit(tyIntSlice, 3).CallWith(2, gogen.InstrFlagEllipsis).EndInit(1).
   518  		NewVarStart(tyInt, "n6").Val(fnAdd).Typ(tyString).Index(1, false).Val("hello").Val(myInts).CallWith(2, gogen.InstrFlagEllipsis).EndInit(1).
   519  		NewVarStart(tyInt, "n7").Val(fnAdd).Typ(tyString).Typ(tyInt).Index(2, false).Val("hello").Val(1).Val(2).Val(3).SliceLit(tyIntSlice, 3).CallWith(2, gogen.InstrFlagEllipsis).EndInit(1).
   520  		NewVarStart(tyIntPointer, "p1").Val(fnLoader).Typ(tyIntPointer).Index(1, false).Val(nil).Val(1).Call(2).EndInit(1).
   521  		NewVarStart(tyIntPointer, "p2").Val(fnLoader).Typ(tyIntPointer).Typ(tyInt).Index(2, false).Val(nil).Val(1).Call(2).EndInit(1).
   522  		NewAutoVar(0, "fn1", &fn1).VarRef(fn1).Val(fnLoader).Typ(tyIntPointer).Typ(tyInt).Index(2, false).Assign(1, 1).EndStmt().
   523  		Val(fn1).Val(nil).Val(1).Call(2).EndStmt().
   524  		End()
   525  	domTest(t, pkg, `package main
   526  
   527  import "foo"
   528  
   529  func main() {
   530  	_ = foo.At[[]int]
   531  	_ = foo.Sum[int]
   532  	_ = foo.Loader[int, int]
   533  	_ = foo.Add[string, int]
   534  	var s1 int = foo.Sum([]int{1, 2, 3})
   535  	var s2 int = foo.Sum[int]([]int{1, 2, 3})
   536  	var v1 int = foo.At([]int{1, 2, 3}, 1)
   537  	var v2 int = foo.At[[]int]([]int{1, 2, 3}, 1)
   538  	var v3 int = foo.At[[]int, int]([]int{1, 2, 3}, 1)
   539  	var n1 int = foo.Add("hello", 1, 2, 3)
   540  	var n2 int = foo.Add[string]("hello", 1, 2, 3)
   541  	var n3 int = foo.Add[string, int]("hello", 1, 2, 3)
   542  	var n4 int = foo.Add("hello", []int{1, 2, 3}...)
   543  	var n5 int = foo.Add("hello", []int{1, 2, 3}...)
   544  	var n6 int = foo.Add[string]("hello", foo.MyInts...)
   545  	var n7 int = foo.Add[string, int]("hello", []int{1, 2, 3}...)
   546  	var p1 *int = foo.Loader[*int](nil, 1)
   547  	var p2 *int = foo.Loader[*int, int](nil, 1)
   548  	var fn1 func(p1 *int, p2 int) *int
   549  	fn1 = foo.Loader[*int, int]
   550  	fn1(nil, 1)
   551  }
   552  `)
   553  }
   554  
   555  func TestTypeParamsErrorInstantiate(t *testing.T) {
   556  	const src = `package foo
   557  
   558  type Number interface {
   559  	~int | float64
   560  }
   561  
   562  func Sum[T Number](vec []T) T {
   563  	var sum T
   564  	for _, elt := range vec {
   565  		sum = sum + elt
   566  	}
   567  	return sum
   568  }
   569  
   570  var	SumInt = Sum[int]
   571  `
   572  	gt := newGoxTest()
   573  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   574  	if err != nil {
   575  		t.Fatal(err)
   576  	}
   577  
   578  	pkg := gt.NewPackage("", "main")
   579  	pkgRef := pkg.Import("foo")
   580  	fnSum := pkgRef.Ref("Sum")
   581  	tyUint := types.Typ[types.Uint]
   582  
   583  	var msg string
   584  	switch runtime.Version()[:6] {
   585  	case "go1.18":
   586  		msg = `./foo.gop:5:40: uint does not implement foo.Number`
   587  	case "go1.19":
   588  		msg = `./foo.gop:5:40: uint does not implement foo.Number (uint missing in ~int | float64)`
   589  	default:
   590  		msg = `./foo.gop:5:40: uint does not satisfy foo.Number (uint missing in ~int | float64)`
   591  	}
   592  	codeErrorTestEx(t, pkg, msg, func(pkg *gogen.Package) {
   593  		pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   594  			DefineVarStart(0, "sum").Val(fnSum).Typ(tyUint).Index(1, false, source(`foo.Sum[uint]`, 5, 40)).EndInit(1).
   595  			End()
   596  	})
   597  }
   598  
   599  func TestTypeParamsErrorMatch(t *testing.T) {
   600  	const src = `package foo
   601  
   602  func At[T interface{ ~[]E }, E any](x T, i int) E {
   603  	return x[i]
   604  }
   605  
   606  var	AtInt = At[[]int]
   607  `
   608  
   609  	gt := newGoxTest()
   610  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   611  	if err != nil {
   612  		t.Fatal(err)
   613  	}
   614  
   615  	pkg := gt.NewPackage("", "main")
   616  	pkgRef := pkg.Import("foo")
   617  	fnAt := pkgRef.Ref("At")
   618  	tyAtInt := pkgRef.Ref("AtInt").Type()
   619  	tyInt := types.Typ[types.Int]
   620  
   621  	var msg string
   622  	switch runtime.Version()[:6] {
   623  	case "go1.18", "go1.19":
   624  		msg = `./foo.gop:5:40: T does not match ~[]E`
   625  	case "go1.20":
   626  		msg = `./foo.gop:5:40: int does not match ~[]E`
   627  	default:
   628  		msg = `./foo.gop:5:40: T (type int) does not satisfy interface{~[]E}`
   629  	}
   630  	codeErrorTestEx(t, pkg, msg, func(pkg *gogen.Package) {
   631  		pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   632  			NewVarStart(tyAtInt, "at").Val(fnAt).Typ(tyInt).Index(1, false, source(`foo.At[int]`, 5, 40)).EndInit(1).
   633  			End()
   634  	})
   635  }
   636  
   637  func TestTypeParamsErrInferFunc(t *testing.T) {
   638  	const src = `package foo
   639  
   640  func Loader[T1 any, T2 any](p1 T1, p2 T2) T1 {
   641  	return p1
   642  }
   643  `
   644  	gt := newGoxTest()
   645  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   646  	if err != nil {
   647  		t.Fatal(err)
   648  	}
   649  	pkg := gt.NewPackage("", "main")
   650  	pkgRef := pkg.Import("foo")
   651  	fnLoader := pkgRef.Ref("Loader")
   652  	tyInt := types.Typ[types.Int]
   653  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: cannot infer T2 (foo.go:3:21)`,
   654  		func(pkg *gogen.Package) {
   655  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   656  				DefineVarStart(0, "v1").Val(fnLoader).Typ(tyInt).Index(1, false, source(`v1 := foo.Loader[int]`, 5, 40)).EndInit(1).
   657  				End()
   658  		})
   659  }
   660  
   661  func TestTypeParamsErrArgumentsParameters1(t *testing.T) {
   662  	const src = `package foo
   663  
   664  type Data[T1 any, T2 any] struct {
   665  	v1 T1
   666  	v2 T2
   667  }
   668  `
   669  	gt := newGoxTest()
   670  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   671  	if err != nil {
   672  		t.Fatal(err)
   673  	}
   674  	pkg := gt.NewPackage("", "main")
   675  	pkgRef := pkg.Import("foo")
   676  	tyData := pkgRef.Ref("Data").Type()
   677  	tyInt := types.Typ[types.Int]
   678  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: got 1 type arguments but foo.Data[T1, T2 any] has 2 type parameters`,
   679  		func(pkg *gogen.Package) {
   680  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   681  				DefineVarStart(0, "v1").Typ(tyData).Typ(tyInt).Index(1, false, source(`foo.Data[int]`, 5, 40)).Star().Val(nil).Call(1).EndInit(1).
   682  				End()
   683  		})
   684  }
   685  
   686  func TestTypeParamsErrArgumentsParameters2(t *testing.T) {
   687  	const src = `package foo
   688  
   689  type Data[T1 any, T2 any] struct {
   690  	v1 T1
   691  	v2 T2
   692  }
   693  `
   694  	gt := newGoxTest()
   695  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   696  	if err != nil {
   697  		t.Fatal(err)
   698  	}
   699  	pkg := gt.NewPackage("", "main")
   700  	pkgRef := pkg.Import("foo")
   701  	tyData := pkgRef.Ref("Data").Type()
   702  	tyInt := types.Typ[types.Int]
   703  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: got 3 type arguments but foo.Data[T1, T2 any] has 2 type parameters`,
   704  		func(pkg *gogen.Package) {
   705  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   706  				DefineVarStart(0, "v1").Typ(tyData).Typ(tyInt).Typ(tyInt).Typ(tyInt).Index(3, false, source(`foo.Data[int,int,int]`, 5, 40)).Star().Val(nil).Call(1).EndInit(1).
   707  				End()
   708  		})
   709  }
   710  
   711  func TestTypeParamsErrArgumentsParameters3(t *testing.T) {
   712  	const src = `package foo
   713  
   714  func Test[T1 any, T2 any](t1 T1, t2 T2) {
   715  	println(t1,t2)
   716  }
   717  `
   718  	gt := newGoxTest()
   719  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   720  	if err != nil {
   721  		t.Fatal(err)
   722  	}
   723  	pkg := gt.NewPackage("", "main")
   724  	pkgRef := pkg.Import("foo")
   725  	fnTest := pkgRef.Ref("Test")
   726  	tyInt := types.Typ[types.Int]
   727  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: got 3 type arguments but func[T1, T2 any](t1 T1, t2 T2) has 2 type parameters`,
   728  		func(pkg *gogen.Package) {
   729  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   730  				Val(fnTest).Typ(tyInt).Typ(tyInt).Typ(tyInt).Index(3, false, source(`foo.Test[int,int,int]`, 5, 40)).Val(1).Val(1).Call(2).EndStmt().
   731  				End()
   732  		})
   733  }
   734  
   735  func TestTypeParamsErrCallArguments1(t *testing.T) {
   736  	const src = `package foo
   737  
   738  func Test[T1 any, T2 any](t1 T1, t2 T2) {
   739  	println(t1,t2)
   740  }
   741  `
   742  	gt := newGoxTest()
   743  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   744  	if err != nil {
   745  		t.Fatal(err)
   746  	}
   747  	pkg := gt.NewPackage("", "main")
   748  	pkgRef := pkg.Import("foo")
   749  	fnTest := pkgRef.Ref("Test")
   750  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: not enough arguments in call to foo.Test
   751  	have (untyped int)
   752  	want (T1, T2)`,
   753  		func(pkg *gogen.Package) {
   754  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   755  				Val(fnTest).Val(1).CallWith(1, 0, source("foo.Test(1)", 5, 40)).EndStmt().
   756  				End()
   757  		})
   758  }
   759  
   760  func TestTypeParamsErrCallArguments2(t *testing.T) {
   761  	const src = `package foo
   762  
   763  func Test[T1 any, T2 any](t1 T1, t2 T2) {
   764  	println(t1,t2)
   765  }
   766  `
   767  	gt := newGoxTest()
   768  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   769  	if err != nil {
   770  		t.Fatal(err)
   771  	}
   772  	pkg := gt.NewPackage("", "main")
   773  	pkgRef := pkg.Import("foo")
   774  	fnTest := pkgRef.Ref("Test")
   775  
   776  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: too many arguments in call to foo.Test
   777  	have (untyped int, untyped int, untyped int)
   778  	want (T1, T2)`,
   779  		func(pkg *gogen.Package) {
   780  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   781  				Val(fnTest).Val(1).Val(2).Val(3).CallWith(3, 0, source("foo.Test(1,2,3)", 5, 40)).EndStmt().
   782  				End()
   783  		})
   784  }
   785  
   786  func TestTypeParamsErrCallArguments3(t *testing.T) {
   787  	const src = `package foo
   788  
   789  func Test[T1 any, T2 any]() {
   790  	var t1 T1
   791  	var t2 T2
   792  	println(t1,t2)
   793  }
   794  `
   795  	gt := newGoxTest()
   796  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   797  	if err != nil {
   798  		t.Fatal(err)
   799  	}
   800  	pkg := gt.NewPackage("", "main")
   801  	pkgRef := pkg.Import("foo")
   802  	fnTest := pkgRef.Ref("Test")
   803  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: too many arguments in call to foo.Test
   804  	have (untyped int, untyped int)
   805  	want ()`,
   806  		func(pkg *gogen.Package) {
   807  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   808  				Val(fnTest).Val(1).Val(2).CallWith(2, 0, source("foo.Test(1,2)", 5, 40)).EndStmt().
   809  				End()
   810  		})
   811  }
   812  
   813  func TestTypeParamsErrCallVariadicArguments1(t *testing.T) {
   814  	const src = `package foo
   815  
   816  func Add[T1 any, T2 ~int](v1 T1, v2 ...T2) (sum T2) {
   817  	println(v1)
   818  	for _, v := range v2 {
   819  		sum += v
   820  	}
   821  	return sum
   822  }
   823  `
   824  	gt := newGoxTest()
   825  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   826  	if err != nil {
   827  		t.Fatal(err)
   828  	}
   829  	pkg := gt.NewPackage("", "main")
   830  	pkgRef := pkg.Import("foo")
   831  	fnAdd := pkgRef.Ref("Add")
   832  
   833  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: not enough arguments in call to foo.Add
   834  	have ()
   835  	want (T1, ...T2)`,
   836  		func(pkg *gogen.Package) {
   837  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   838  				Val(fnAdd).CallWith(0, 0, source("foo.Add()", 5, 40)).EndStmt().
   839  				End()
   840  		})
   841  }
   842  
   843  func TestTypeParamsErrCallVariadicArguments2(t *testing.T) {
   844  	const src = `package foo
   845  
   846  func Add[T1 any, T2 ~int](v1 T1, v2 ...T2) (sum T2) {
   847  	println(v1)
   848  	for _, v := range v2 {
   849  		sum += v
   850  	}
   851  	return sum
   852  }
   853  `
   854  	gt := newGoxTest()
   855  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   856  	if err != nil {
   857  		t.Fatal(err)
   858  	}
   859  	pkg := gt.NewPackage("", "main")
   860  	pkgRef := pkg.Import("foo")
   861  	fnAdd := pkgRef.Ref("Add")
   862  
   863  	// not pass source to foo.Add
   864  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: cannot infer T2 (-)`,
   865  		func(pkg *gogen.Package) {
   866  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   867  				Val(fnAdd).Val(1).CallWith(1, 0, source("foo.Add(1)", 5, 40)).EndStmt().
   868  				End()
   869  		})
   870  }
   871  
   872  func TestTypeParamsErrorCall(t *testing.T) {
   873  	const src = `package foo
   874  
   875  type Number interface {
   876  	~int | float64
   877  }
   878  
   879  func Sum[T Number](vec []T) T {
   880  	var sum T
   881  	for _, elt := range vec {
   882  		sum = sum + elt
   883  	}
   884  	return sum
   885  }
   886  `
   887  	gt := newGoxTest()
   888  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   889  	if err != nil {
   890  		t.Fatal(err)
   891  	}
   892  	pkg := gt.NewPackage("", "main")
   893  	pkgRef := pkg.Import("foo")
   894  	fnSum := pkgRef.Ref("Sum")
   895  	tyUint := types.Typ[types.Uint]
   896  	tyUintSlice := types.NewSlice(tyUint)
   897  
   898  	var msg string
   899  	switch runtime.Version()[:6] {
   900  	case "go1.18":
   901  		msg = `./foo.gop:5:40: uint does not implement foo.Number`
   902  	case "go1.19":
   903  		msg = `./foo.gop:5:40: uint does not implement foo.Number (uint missing in ~int | float64)`
   904  	default:
   905  		msg = `./foo.gop:5:40: uint does not satisfy foo.Number (uint missing in ~int | float64)`
   906  	}
   907  	codeErrorTestEx(t, pkg, msg, func(pkg *gogen.Package) {
   908  		pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   909  			Val(fnSum).Val(1).Val(2).Val(3).SliceLit(tyUintSlice, 3).CallWith(1, 0, source(`foo.Sum([]uint{1,2,3})`, 5, 40)).EndInit(1).
   910  			End()
   911  	})
   912  }
   913  
   914  func TestTypeParamsErrorInferCall(t *testing.T) {
   915  	const src = `package foo
   916  
   917  func Loader[T1 any, T2 any](p1 T1, p2 T2) T1 {
   918  	return p1
   919  }
   920  `
   921  	gt := newGoxTest()
   922  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   923  	if err != nil {
   924  		t.Fatal(err)
   925  	}
   926  	pkg := gt.NewPackage("", "main")
   927  	pkgRef := pkg.Import("foo")
   928  	fnLoader := pkgRef.Ref("Loader")
   929  	tyInt := types.Typ[types.Int]
   930  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: cannot infer T2 (foo.go:3:21)`,
   931  		func(pkg *gogen.Package) {
   932  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   933  				Val(fnLoader).Typ(tyInt).Index(1, false, source(`foo.Loader[int]`, 5, 40)).Val(10).Val(nil).CallWith(2, 0, source(`foo.Loader[int]`, 5, 40)).EndStmt().
   934  				End()
   935  		})
   936  }
   937  
   938  func TestTypeParamErrGenericType(t *testing.T) {
   939  	const src = `package foo
   940  
   941  type Data struct {
   942  }
   943  `
   944  	gt := newGoxTest()
   945  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   946  	if err != nil {
   947  		t.Fatal(err)
   948  	}
   949  	pkg := gt.NewPackage("", "main")
   950  	pkgRef := pkg.Import("foo")
   951  	tyData := pkgRef.Ref("Data").Type()
   952  	tyInt := types.Typ[types.Int]
   953  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: foo.Data is not a generic type`,
   954  		func(pkg *gogen.Package) {
   955  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   956  				DefineVarStart(0, "v1").Typ(tyData).Typ(tyInt).Index(1, false, source(`foo.Data[int]`, 5, 40)).Star().Val(nil).Call(1).EndInit(1).
   957  				End()
   958  		})
   959  }
   960  
   961  func TestTypeParamErrGenericType2(t *testing.T) {
   962  	gt := newGoxTest()
   963  	pkg := gt.NewPackage("", "main")
   964  	tyInt := types.Typ[types.Int]
   965  	tyString := types.Typ[types.String]
   966  
   967  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: string is not a generic type`,
   968  		func(pkg *gogen.Package) {
   969  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   970  				DefineVarStart(0, "v1").Typ(tyString).Typ(tyInt).Index(1, false, source(`string[int]`, 5, 40)).Star().Val(nil).Call(1).EndInit(1).
   971  				End()
   972  		})
   973  }
   974  
   975  func TestTypeParamErrGenericFunc(t *testing.T) {
   976  	const src = `package foo
   977  
   978  func Loader(n int) string {
   979  	return ""
   980  }
   981  `
   982  	gt := newGoxTest()
   983  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
   984  	if err != nil {
   985  		t.Fatal(err)
   986  	}
   987  	pkg := gt.NewPackage("", "main")
   988  	pkgRef := pkg.Import("foo")
   989  	fnLoader := pkgRef.Ref("Loader")
   990  	tyInt := types.Typ[types.Int]
   991  
   992  	codeErrorTestEx(t, pkg, `./foo.gop:5:40: invalid operation: cannot index foo.Loader (value of type func(n int) string)`,
   993  		func(pkg *gogen.Package) {
   994  			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   995  				DefineVarStart(0, "v1").Val(fnLoader).Typ(tyInt).Index(1, false, source(`v1 := foo.Loader[int]`, 5, 40)).EndInit(1).
   996  				End()
   997  		})
   998  }
   999  
  1000  func TestGenTypeParamsFunc(t *testing.T) {
  1001  	pkg := newMainPackage()
  1002  	ut1 := types.NewUnion([]*types.Term{types.NewTerm(true, types.Typ[types.Int]), types.NewTerm(false, types.Typ[types.Uint])})
  1003  	ut2 := types.NewUnion([]*types.Term{types.NewTerm(true, types.Typ[types.Int])})
  1004  	it := pkg.NewType("T").InitType(pkg, types.NewInterfaceType(nil, []types.Type{ut1}))
  1005  	tp1 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T1", nil), types.Universe.Lookup("any").Type())
  1006  	tp2 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T2", nil), ut2)
  1007  	tp3 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T3", nil), it)
  1008  	p1 := types.NewParam(token.NoPos, pkg.Types, "p1", tp1)
  1009  	p2 := types.NewParam(token.NoPos, pkg.Types, "p2", tp2)
  1010  	p3 := types.NewParam(token.NoPos, pkg.Types, "p3", tp3)
  1011  	sig := types.NewSignatureType(nil, nil, []*types.TypeParam{tp1, tp2, tp3}, types.NewTuple(p1, p2, p3), nil, false)
  1012  	fn1 := pkg.NewFuncDecl(token.NoPos, "test", sig)
  1013  	fn1.BodyStart(pkg).End()
  1014  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  1015  		Val(fn1).Val("hello").Val(100).Val(200).Call(3).EndStmt().
  1016  		Val(fn1).Typ(types.Typ[types.String]).Typ(types.Typ[types.Int]).Typ(types.Typ[types.Uint]).Index(3, false).Val("hello").Val(100).Val(200).Call(3).EndStmt().
  1017  		Val(fn1).Typ(types.Typ[types.String]).Typ(types.Typ[types.Int]).Index(2, false).Val("hello").Val(100).Val(200).Call(3).EndStmt().
  1018  		Val(fn1).Typ(types.Typ[types.String]).Index(1, false).Val("hello").Val(100).Val(200).Call(3).EndStmt().
  1019  		End()
  1020  
  1021  	domTest(t, pkg, `package main
  1022  
  1023  type T interface {
  1024  	~int | uint
  1025  }
  1026  
  1027  func test[T1 any, T2 ~int, T3 T](p1 T1, p2 T2, p3 T3) {
  1028  }
  1029  func main() {
  1030  	test("hello", 100, 200)
  1031  	test[string, int, uint]("hello", 100, 200)
  1032  	test[string, int]("hello", 100, 200)
  1033  	test[string]("hello", 100, 200)
  1034  }
  1035  `)
  1036  }
  1037  
  1038  func TestGenTypeParamsType(t *testing.T) {
  1039  	pkg := newMainPackage()
  1040  	ut := types.NewUnion([]*types.Term{types.NewTerm(true, types.Typ[types.Int]), types.NewTerm(false, types.Typ[types.Uint])})
  1041  	it := pkg.NewType("T").InitType(pkg, types.NewInterfaceType(nil, []types.Type{ut}))
  1042  
  1043  	// type M
  1044  	mp1 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T", nil), ut)
  1045  	mp2 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T", nil), ut)
  1046  	mt1 := pkg.NewType("M").InitType(pkg, types.NewStruct(nil, nil), mp1)
  1047  	msig1 := types.NewSignatureType(types.NewVar(token.NoPos, pkg.Types, "m1", types.NewPointer(mt1)), []*types.TypeParam{mp2}, nil, nil, nil, false)
  1048  	mfn1 := pkg.NewFuncDecl(token.NoPos, "test", msig1)
  1049  	mfn1.BodyStart(pkg).End()
  1050  
  1051  	// type S
  1052  	sp1 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T1", nil), types.Universe.Lookup("any").Type())
  1053  	sp2 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T2", nil), ut)
  1054  	sp3 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T3", nil), it)
  1055  
  1056  	st := types.NewStruct([]*types.Var{
  1057  		types.NewField(token.NoPos, pkg.Types, "f1", sp1, false),
  1058  		types.NewField(token.NoPos, pkg.Types, "f2", sp2, false),
  1059  		types.NewField(token.NoPos, pkg.Types, "f3", sp3, false),
  1060  	}, nil)
  1061  	named := pkg.NewType("S").InitType(pkg, st, sp1, sp2, sp3)
  1062  
  1063  	tp1 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T1", nil), types.Universe.Lookup("any").Type())
  1064  	tp2 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T2", nil), ut)
  1065  	tp3 := types.NewTypeParam(types.NewTypeName(token.NoPos, pkg.Types, "T3", nil), it)
  1066  	p1 := types.NewParam(token.NoPos, pkg.Types, "p1", tp1)
  1067  	p2 := types.NewParam(token.NoPos, pkg.Types, "p2", tp2)
  1068  	p3 := types.NewParam(token.NoPos, pkg.Types, "p3", tp3)
  1069  
  1070  	sig := types.NewSignatureType(types.NewVar(token.NoPos, pkg.Types, "r1", types.NewPointer(named)), []*types.TypeParam{tp1, tp2, tp3}, nil, types.NewTuple(p1, p2, p3), nil, false)
  1071  	fn1 := pkg.NewFuncDecl(token.NoPos, "test", sig)
  1072  	fn1.BodyStart(pkg).End()
  1073  
  1074  	inst, err := types.Instantiate(nil, named, []types.Type{types.Typ[types.String], types.Typ[types.Int], types.Typ[types.Uint]}, true)
  1075  	if err != nil {
  1076  		t.Fatal(err)
  1077  	}
  1078  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  1079  		DefineVarStart(token.NoPos, "s").StructLit(inst, 0, false).UnaryOp(token.AND).EndInit(1).
  1080  		Val(ctxRef(pkg, "s")).MemberVal("test").Val("hello").Val(100).Val(200).Call(3, false).EndStmt().
  1081  		Val(pkg.Builtin().Ref("println")).Val(ctxRef(pkg, "s")).MemberVal("f1").Call(1, false).EndStmt().
  1082  		End()
  1083  
  1084  	domTest(t, pkg, `package main
  1085  
  1086  type T interface {
  1087  	~int | uint
  1088  }
  1089  type M[T ~int | uint] struct {
  1090  }
  1091  
  1092  func (m1 *M[T]) test() {
  1093  }
  1094  
  1095  type S[T1 any, T2 ~int | uint, T3 T] struct {
  1096  	f1 T1
  1097  	f2 T2
  1098  	f3 T3
  1099  }
  1100  
  1101  func (r1 *S[T1, T2, T3]) test(p1 T1, p2 T2, p3 T3) {
  1102  }
  1103  func main() {
  1104  	s := &S[string, int, uint]{}
  1105  	s.test("hello", 100, 200)
  1106  	println(s.f1)
  1107  }
  1108  `)
  1109  }
  1110  
  1111  func TestTypeParamsArgumentsSignature(t *testing.T) {
  1112  	const src = `package foo
  1113  
  1114  import "fmt"
  1115  
  1116  func ListMap[X any, T any](x X, ar []T, fn func(v T) T, dump func(i int,x X, v T)) {
  1117  	for i, v := range ar {
  1118  		ar[i] = fn(v)
  1119  		dump(i, x, ar[i])
  1120  	}
  1121  }
  1122  
  1123  func ListMapv[X any, T any](x X, ar []T, fn func(v T) T, dump ...func(i int,x X, v T)) {
  1124  	for i, v := range ar {
  1125  		ar[i] = fn(v)
  1126  		dump[0](i, x, ar[i])
  1127  	}
  1128  }
  1129  
  1130  
  1131  func Add[N ~int](x N) N {
  1132  	return x+x
  1133  }
  1134  
  1135  func Dump[N any, X any, Y any](i N, x X, y Y) {
  1136  	fmt.Println(i, x, y)
  1137  }
  1138  
  1139  func Dump2[X any, Y any](i int, x X, y Y) {
  1140  	fmt.Println(i, x, y)
  1141  }
  1142  
  1143  var Numbers = []int{1,2,3,4}
  1144  `
  1145  	gt := newGoxTest()
  1146  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
  1147  	if err != nil {
  1148  		t.Fatal(err)
  1149  	}
  1150  	pkg := gt.NewPackage("", "main")
  1151  	fooRef := pkg.Import("foo")
  1152  	pkg.NewFunc(nil, "_", nil, nil, false).BodyStart(pkg).
  1153  		Val(fooRef.Ref("ListMap")).
  1154  		Val(100).Val(fooRef.Ref("Numbers")).Val(fooRef.Ref("Add")).Val(fooRef.Ref("Dump")).
  1155  		Call(4).EndStmt().
  1156  		Val(fooRef.Ref("ListMap")).
  1157  		Val("a").Val(fooRef.Ref("Numbers")).Val(fooRef.Ref("Add")).Val(fooRef.Ref("Dump")).
  1158  		Typ(types.Typ[types.Int]).Index(1, false).
  1159  		Call(4).EndStmt().
  1160  		Val(fooRef.Ref("ListMap")).
  1161  		Val("a").Val(fooRef.Ref("Numbers")).Val(fooRef.Ref("Add")).Val(fooRef.Ref("Dump2")).
  1162  		Call(4).EndStmt().
  1163  		End()
  1164  	pkg.NewFunc(nil, "_", nil, nil, false).BodyStart(pkg).
  1165  		Val(fooRef.Ref("ListMapv")).
  1166  		Val(100).Val(fooRef.Ref("Numbers")).Val(fooRef.Ref("Add")).Val(fooRef.Ref("Dump")). //.SliceLit(tyFuncList, 1).
  1167  		Val(fooRef.Ref("Dump")).
  1168  		Typ(types.Typ[types.Int]).Index(1, false).
  1169  		Val(fooRef.Ref("Dump2")).
  1170  		Call(6, false).EndStmt().
  1171  		Val(fooRef.Ref("ListMapv")).
  1172  		Val("a").Val(fooRef.Ref("Numbers")).Val(fooRef.Ref("Add")).Val(fooRef.Ref("Dump")). //.SliceLit(tyFuncList, 1).
  1173  		Val(fooRef.Ref("Dump")).
  1174  		Typ(types.Typ[types.Int]).Index(1, false).
  1175  		Val(fooRef.Ref("Dump2")).
  1176  		Call(6, false).EndStmt().
  1177  		End()
  1178  	domTest(t, pkg, `package main
  1179  
  1180  import "foo"
  1181  
  1182  func _() {
  1183  	foo.ListMap(100, foo.Numbers, foo.Add[int], foo.Dump[int, int, int])
  1184  	foo.ListMap("a", foo.Numbers, foo.Add[int], foo.Dump[int, string, int])
  1185  	foo.ListMap("a", foo.Numbers, foo.Add[int], foo.Dump2[string, int])
  1186  }
  1187  func _() {
  1188  	foo.ListMapv(100, foo.Numbers, foo.Add[int], foo.Dump[int, int, int], foo.Dump[int, int, int], foo.Dump2[int, int])
  1189  	foo.ListMapv("a", foo.Numbers, foo.Add[int], foo.Dump[int, string, int], foo.Dump[int, string, int], foo.Dump2[string, int])
  1190  }
  1191  `)
  1192  }