Source file src/go/types/instantiate_test.go

     1  // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
     2  // Source: ../../cmd/compile/internal/types2/instantiate_test.go
     3  
     4  // Copyright 2021 The Go Authors. All rights reserved.
     5  // Use of this source code is governed by a BSD-style
     6  // license that can be found in the LICENSE file.
     7  package types_test
     8  
     9  import (
    10  	. "go/types"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  func TestInstantiateEquality(t *testing.T) {
    16  	emptySignature := NewSignatureType(nil, nil, nil, nil, nil, false)
    17  	tests := []struct {
    18  		src       string
    19  		name1     string
    20  		targs1    []Type
    21  		name2     string
    22  		targs2    []Type
    23  		wantEqual bool
    24  	}{
    25  		{
    26  			"package basictype; type T[P any] int",
    27  			"T", []Type{Typ[Int]},
    28  			"T", []Type{Typ[Int]},
    29  			true,
    30  		},
    31  		{
    32  			"package differenttypeargs; type T[P any] int",
    33  			"T", []Type{Typ[Int]},
    34  			"T", []Type{Typ[String]},
    35  			false,
    36  		},
    37  		{
    38  			"package typeslice; type T[P any] int",
    39  			"T", []Type{NewSlice(Typ[Int])},
    40  			"T", []Type{NewSlice(Typ[Int])},
    41  			true,
    42  		},
    43  		{
    44  			// interface{interface{...}} is equivalent to interface{...}
    45  			"package equivalentinterfaces; type T[P any] int",
    46  			"T", []Type{
    47  				NewInterfaceType([]*Func{NewFunc(nopos, nil, "M", emptySignature)}, nil),
    48  			},
    49  			"T", []Type{
    50  				NewInterfaceType(
    51  					nil,
    52  					[]Type{
    53  						NewInterfaceType([]*Func{NewFunc(nopos, nil, "M", emptySignature)}, nil),
    54  					},
    55  				),
    56  			},
    57  			true,
    58  		},
    59  		{
    60  			// int|string is equivalent to string|int
    61  			"package equivalenttypesets; type T[P any] int",
    62  			"T", []Type{
    63  				NewInterfaceType(nil, []Type{
    64  					NewUnion([]*Term{NewTerm(false, Typ[Int]), NewTerm(false, Typ[String])}),
    65  				}),
    66  			},
    67  			"T", []Type{
    68  				NewInterfaceType(nil, []Type{
    69  					NewUnion([]*Term{NewTerm(false, Typ[String]), NewTerm(false, Typ[Int])}),
    70  				}),
    71  			},
    72  			true,
    73  		},
    74  		{
    75  			"package basicfunc; func F[P any]() {}",
    76  			"F", []Type{Typ[Int]},
    77  			"F", []Type{Typ[Int]},
    78  			true,
    79  		},
    80  		{
    81  			"package funcslice; func F[P any]() {}",
    82  			"F", []Type{NewSlice(Typ[Int])},
    83  			"F", []Type{NewSlice(Typ[Int])},
    84  			true,
    85  		},
    86  		{
    87  			"package funcwithparams; func F[P any](x string) float64 { return 0 }",
    88  			"F", []Type{Typ[Int]},
    89  			"F", []Type{Typ[Int]},
    90  			true,
    91  		},
    92  		{
    93  			"package differentfuncargs; func F[P any](x string) float64 { return 0 }",
    94  			"F", []Type{Typ[Int]},
    95  			"F", []Type{Typ[String]},
    96  			false,
    97  		},
    98  		{
    99  			"package funcequality; func F1[P any](x int) {}; func F2[Q any](x int) {}",
   100  			"F1", []Type{Typ[Int]},
   101  			"F2", []Type{Typ[Int]},
   102  			false,
   103  		},
   104  		{
   105  			"package funcsymmetry; func F1[P any](x P) {}; func F2[Q any](x Q) {}",
   106  			"F1", []Type{Typ[Int]},
   107  			"F2", []Type{Typ[Int]},
   108  			false,
   109  		},
   110  	}
   111  
   112  	for _, test := range tests {
   113  		pkg := mustTypecheck(test.src, nil, nil)
   114  
   115  		t.Run(pkg.Name(), func(t *testing.T) {
   116  			ctxt := NewContext()
   117  
   118  			T1 := pkg.Scope().Lookup(test.name1).Type()
   119  			res1, err := Instantiate(ctxt, T1, test.targs1, false)
   120  			if err != nil {
   121  				t.Fatal(err)
   122  			}
   123  
   124  			T2 := pkg.Scope().Lookup(test.name2).Type()
   125  			res2, err := Instantiate(ctxt, T2, test.targs2, false)
   126  			if err != nil {
   127  				t.Fatal(err)
   128  			}
   129  
   130  			if gotEqual := res1 == res2; gotEqual != test.wantEqual {
   131  				t.Errorf("%s == %s: %t, want %t", res1, res2, gotEqual, test.wantEqual)
   132  			}
   133  		})
   134  	}
   135  }
   136  
   137  func TestInstantiateNonEquality(t *testing.T) {
   138  	const src = "package p; type T[P any] int"
   139  	pkg1 := mustTypecheck(src, nil, nil)
   140  	pkg2 := mustTypecheck(src, nil, nil)
   141  	// We consider T1 and T2 to be distinct types, so their instances should not
   142  	// be deduplicated by the context.
   143  	T1 := pkg1.Scope().Lookup("T").Type().(*Named)
   144  	T2 := pkg2.Scope().Lookup("T").Type().(*Named)
   145  	ctxt := NewContext()
   146  	res1, err := Instantiate(ctxt, T1, []Type{Typ[Int]}, false)
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  	res2, err := Instantiate(ctxt, T2, []Type{Typ[Int]}, false)
   151  	if err != nil {
   152  		t.Fatal(err)
   153  	}
   154  	if res1 == res2 {
   155  		t.Errorf("instance from pkg1 (%s) is pointer-equivalent to instance from pkg2 (%s)", res1, res2)
   156  	}
   157  	if Identical(res1, res2) {
   158  		t.Errorf("instance from pkg1 (%s) is identical to instance from pkg2 (%s)", res1, res2)
   159  	}
   160  }
   161  
   162  func TestMethodInstantiation(t *testing.T) {
   163  	const prefix = `package p
   164  
   165  type T[P any] struct{}
   166  
   167  var X T[int]
   168  
   169  `
   170  	tests := []struct {
   171  		decl string
   172  		want string
   173  	}{
   174  		{"func (r T[P]) m() P", "func (T[int]).m() int"},
   175  		{"func (r T[P]) m(P)", "func (T[int]).m(int)"},
   176  		{"func (r *T[P]) m(P)", "func (*T[int]).m(int)"},
   177  		{"func (r T[P]) m() T[P]", "func (T[int]).m() T[int]"},
   178  		{"func (r T[P]) m(T[P])", "func (T[int]).m(T[int])"},
   179  		{"func (r T[P]) m(T[P], P, string)", "func (T[int]).m(T[int], int, string)"},
   180  		{"func (r T[P]) m(T[P], T[string], T[int])", "func (T[int]).m(T[int], T[string], T[int])"},
   181  	}
   182  
   183  	for _, test := range tests {
   184  		src := prefix + test.decl
   185  		pkg := mustTypecheck(src, nil, nil)
   186  		typ := NewPointer(pkg.Scope().Lookup("X").Type())
   187  		obj, _, _ := LookupFieldOrMethod(typ, false, pkg, "m")
   188  		m, _ := obj.(*Func)
   189  		if m == nil {
   190  			t.Fatalf(`LookupFieldOrMethod(%s, "m") = %v, want func m`, typ, obj)
   191  		}
   192  		if got := ObjectString(m, RelativeTo(pkg)); got != test.want {
   193  			t.Errorf("instantiated %q, want %q", got, test.want)
   194  		}
   195  	}
   196  }
   197  
   198  func TestImmutableSignatures(t *testing.T) {
   199  	const src = `package p
   200  
   201  type T[P any] struct{}
   202  
   203  func (T[P]) m() {}
   204  
   205  var _ T[int]
   206  `
   207  	pkg := mustTypecheck(src, nil, nil)
   208  	typ := pkg.Scope().Lookup("T").Type().(*Named)
   209  	obj, _, _ := LookupFieldOrMethod(typ, false, pkg, "m")
   210  	if obj == nil {
   211  		t.Fatalf(`LookupFieldOrMethod(%s, "m") = %v, want func m`, typ, obj)
   212  	}
   213  
   214  	// Verify that the original method is not mutated by instantiating T (this
   215  	// bug manifested when subst did not return a new signature).
   216  	want := "func (T[P]).m()"
   217  	if got := stripAnnotations(ObjectString(obj, RelativeTo(pkg))); got != want {
   218  		t.Errorf("instantiated %q, want %q", got, want)
   219  	}
   220  }
   221  
   222  // Copied from errors.go.
   223  func stripAnnotations(s string) string {
   224  	var buf strings.Builder
   225  	for _, r := range s {
   226  		// strip #'s and subscript digits
   227  		if r < '₀' || '₀'+10 <= r { // '₀' == U+2080
   228  			buf.WriteRune(r)
   229  		}
   230  	}
   231  	if buf.Len() < len(s) {
   232  		return buf.String()
   233  	}
   234  	return s
   235  }
   236  

View as plain text