...

Source file src/golang.org/x/tools/go/ssa/subst_test.go

Documentation: golang.org/x/tools/go/ssa

     1  // Copyright 2022 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssa
     6  
     7  import (
     8  	"go/ast"
     9  	"go/parser"
    10  	"go/token"
    11  	"go/types"
    12  	"testing"
    13  )
    14  
    15  func TestSubst(t *testing.T) {
    16  	const source = `
    17  package P
    18  
    19  type t0 int
    20  func (t0) f()
    21  type t1 interface{ f() }
    22  type t2 interface{ g() }
    23  type t3 interface{ ~int }
    24  
    25  func Fn0[T t1](x T) T {
    26  	x.f()
    27  	return x
    28  }
    29  
    30  type A[T any] [4]T
    31  type B[T any] []T
    32  type C[T, S any] []struct{s S; t T}
    33  type D[T, S any] *struct{s S; t *T}
    34  type E[T, S any] interface{ F() (T, S) }
    35  type F[K comparable, V any] map[K]V
    36  type G[T any] chan *T
    37  type H[T any] func() T
    38  type I[T any] struct{x, y, z int; t T}
    39  type J[T any] interface{ t1 }
    40  type K[T any] interface{ t1; F() T }
    41  type L[T any] interface{ F() T; J[T] }
    42  
    43  var _ L[int] = Fn0[L[int]](nil)
    44  `
    45  
    46  	fset := token.NewFileSet()
    47  	f, err := parser.ParseFile(fset, "hello.go", source, 0)
    48  	if err != nil {
    49  		t.Fatal(err)
    50  	}
    51  
    52  	var conf types.Config
    53  	pkg, err := conf.Check("P", fset, []*ast.File{f}, nil)
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  
    58  	for _, test := range []struct {
    59  		expr string   // type expression of Named parameterized type
    60  		args []string // type expressions of args for named
    61  		want string   // expected underlying value after substitution
    62  	}{
    63  		{"A", []string{"string"}, "[4]string"},
    64  		{"A", []string{"int"}, "[4]int"},
    65  		{"B", []string{"int"}, "[]int"},
    66  		{"B", []string{"int8"}, "[]int8"},
    67  		{"C", []string{"int8", "string"}, "[]struct{s string; t int8}"},
    68  		{"C", []string{"string", "int8"}, "[]struct{s int8; t string}"},
    69  		{"D", []string{"int16", "string"}, "*struct{s string; t *int16}"},
    70  		{"E", []string{"int32", "string"}, "interface{F() (int32, string)}"},
    71  		{"F", []string{"int64", "string"}, "map[int64]string"},
    72  		{"G", []string{"uint64"}, "chan *uint64"},
    73  		{"H", []string{"uintptr"}, "func() uintptr"},
    74  		{"I", []string{"t0"}, "struct{x int; y int; z int; t P.t0}"},
    75  		{"J", []string{"t0"}, "interface{P.t1}"},
    76  		{"K", []string{"t0"}, "interface{F() P.t0; P.t1}"},
    77  		{"L", []string{"t0"}, "interface{F() P.t0; P.J[P.t0]}"},
    78  		{"L", []string{"L[t0]"}, "interface{F() P.L[P.t0]; P.J[P.L[P.t0]]}"},
    79  	} {
    80  		// Eval() expr for its type.
    81  		tv, err := types.Eval(fset, pkg, 0, test.expr)
    82  		if err != nil {
    83  			t.Fatalf("Eval(%s) failed: %v", test.expr, err)
    84  		}
    85  		// Eval() test.args[i] to get the i'th type arg.
    86  		var targs []types.Type
    87  		for _, astr := range test.args {
    88  			tv, err := types.Eval(fset, pkg, 0, astr)
    89  			if err != nil {
    90  				t.Fatalf("Eval(%s) failed: %v", astr, err)
    91  			}
    92  			targs = append(targs, tv.Type)
    93  		}
    94  
    95  		T := tv.Type.(*types.Named)
    96  
    97  		subst := makeSubster(types.NewContext(), nil, T.TypeParams(), targs, true)
    98  		sub := subst.typ(T.Underlying())
    99  		if got := sub.String(); got != test.want {
   100  			t.Errorf("subst{%v->%v}.typ(%s) = %v, want %v", test.expr, test.args, T.Underlying(), got, test.want)
   101  		}
   102  	}
   103  }
   104  

View as plain text