Skip to content

Commit

Permalink
inferFunc: support arguments with typeparam signature
Browse files Browse the repository at this point in the history
  • Loading branch information
visualfc committed Mar 24, 2024
1 parent d435e48 commit b4fa438
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 7 deletions.
36 changes: 29 additions & 7 deletions typeparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,25 +318,47 @@ func inferFunc(pkg *Package, fn *internal.Elem, sig *types.Signature, targs []ty
return nil, err
}
xlist := make([]*operand, len(args))
tp := sig.TypeParams()
n := tp.Len()
tparams := make([]*types.TypeParam, n)
for i := 0; i < n; i++ {
tparams[i] = tp.At(i)
}
var targList []*internal.Elem
for i, arg := range args {
xlist[i] = &operand{
mode: value,
expr: arg.Val,
typ: arg.Type,
val: arg.CVal,
}
}
tp := sig.TypeParams()
n := tp.Len()
tparams := make([]*types.TypeParam, n)
for i := 0; i < n; i++ {
tparams[i] = tp.At(i)
if sig, ok := arg.Type.(*types.Signature); ok {
if tp := sig.TypeParams(); tp != nil {
for i := 0; i < n; i++ {
tparams = append(tparams, tp.At(i))
}
targList = append(targList, arg)
}
}
}
targs, err = infer(pkg, fn.Val, tparams, targs, sig.Params(), xlist)
if err != nil {
return nil, err
}
return types.Instantiate(pkg.cb.ctxt, sig, targs, true)
typ, err := types.Instantiate(pkg.cb.ctxt, sig, targs[:n], true)
if err == nil {
for _, targ := range targList {
tsig := targ.Type.(*types.Signature)
tp := tsig.TypeParams()
tn := tp.Len()
tt, err := types.Instantiate(pkg.cb.ctxt, tsig, targs[n:n+tn], true)
if err == nil {
targ.Type = tt
}
n += tn
}
}
return typ, err
}

func inferFuncTargs(pkg *Package, fn *internal.Elem, sig *types.Signature, targs []types.Type) (types.Type, error) {
Expand Down
45 changes: 45 additions & 0 deletions typeparams_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1107,3 +1107,48 @@ func main() {
}
`)
}

func TestTypeParamsArgumentsSignature(t *testing.T) {
const src = `package foo
import "fmt"
func ListMap[T any](ar []T, fn func(v T) T, dump func(i int, v T)) {
for i, v := range ar {
ar[i] = fn(v)
dump(i,ar[i])
}
}
func Add[N ~int](x N) N {
return x+x
}
func Dump[T any](i int, v T) {
fmt.Println(i,v)
}
var Numbers = []int{1,2,3,4}
`
gt := newGoxTest()
_, err := gt.LoadGoPackage("foo", "foo.go", src)
if err != nil {
t.Fatal(err)
}
pkg := gt.NewPackage("", "main")
fooRef := pkg.Import("foo")
pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
Val(fooRef.Ref("ListMap")).
Val(fooRef.Ref("Numbers")).Val(fooRef.Ref("Add")).Val(fooRef.Ref("Dump")).
Call(3).EndStmt().
End()

domTest(t, pkg, `package main
import "foo"
func main() {
foo.ListMap(foo.Numbers, foo.Add, foo.Dump)
}
`)
}

0 comments on commit b4fa438

Please sign in to comment.