aboutsummaryrefslogtreecommitdiff
path: root/go/ssa/builder_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'go/ssa/builder_test.go')
-rw-r--r--go/ssa/builder_test.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/go/ssa/builder_test.go b/go/ssa/builder_test.go
index fd2d21c5d..b3bb09c5e 100644
--- a/go/ssa/builder_test.go
+++ b/go/ssa/builder_test.go
@@ -894,3 +894,114 @@ func TestGenericFunctionSelector(t *testing.T) {
}
}
}
+
+func TestIssue58491(t *testing.T) {
+ // Test that a local type reaches type param in instantiation.
+ testenv.NeedsGo1Point(t, 18)
+ src := `
+ package p
+
+ func foo[T any](blocking func() (T, error)) error {
+ type result struct {
+ res T
+ error // ensure the method set of result is non-empty
+ }
+
+ res := make(chan result, 1)
+ go func() {
+ var r result
+ r.res, r.error = blocking()
+ res <- r
+ }()
+ r := <-res
+ err := r // require the rtype for result when instantiated
+ return err
+ }
+ var Inst = foo[int]
+ `
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, "p.go", src, 0)
+ if err != nil {
+ t.Error(err)
+ }
+ files := []*ast.File{f}
+
+ pkg := types.NewPackage("p", "")
+ conf := &types.Config{}
+ p, _, err := ssautil.BuildPackage(conf, fset, pkg, files, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+
+ // Find the local type result instantiated with int.
+ var found bool
+ for _, rt := range p.Prog.RuntimeTypes() {
+ if n, ok := rt.(*types.Named); ok {
+ if u, ok := n.Underlying().(*types.Struct); ok {
+ found = true
+ if got, want := n.String(), "p.result"; got != want {
+ t.Errorf("Expected the name %s got: %s", want, got)
+ }
+ if got, want := u.String(), "struct{res int; error}"; got != want {
+ t.Errorf("Expected the underlying type of %s to be %s. got %s", n, want, got)
+ }
+ }
+ }
+ }
+ if !found {
+ t.Error("Failed to find any Named to struct types")
+ }
+}
+
+func TestIssue58491Rec(t *testing.T) {
+ // Roughly the same as TestIssue58491 but with a recursive type.
+ testenv.NeedsGo1Point(t, 18)
+ src := `
+ package p
+
+ func foo[T any]() error {
+ type result struct {
+ res T
+ next *result
+ error // ensure the method set of result is non-empty
+ }
+
+ r := &result{}
+ err := r // require the rtype for result when instantiated
+ return err
+ }
+ var Inst = foo[int]
+ `
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, "p.go", src, 0)
+ if err != nil {
+ t.Error(err)
+ }
+ files := []*ast.File{f}
+
+ pkg := types.NewPackage("p", "")
+ conf := &types.Config{}
+ p, _, err := ssautil.BuildPackage(conf, fset, pkg, files, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+
+ // Find the local type result instantiated with int.
+ var found bool
+ for _, rt := range p.Prog.RuntimeTypes() {
+ if n, ok := rt.(*types.Named); ok {
+ if u, ok := n.Underlying().(*types.Struct); ok {
+ found = true
+ if got, want := n.String(), "p.result"; got != want {
+ t.Errorf("Expected the name %s got: %s", want, got)
+ }
+ if got, want := u.String(), "struct{res int; next *p.result; error}"; got != want {
+ t.Errorf("Expected the underlying type of %s to be %s. got %s", n, want, got)
+ }
+ }
+ }
+ }
+ if !found {
+ t.Error("Failed to find any Named to struct types")
+ }
+}