...

Source file src/go/types/methodset_test.go

Documentation: go/types

		 1  // Copyright 2021 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 types_test
		 6  
		 7  import (
		 8  	"testing"
		 9  
		10  	"go/internal/typeparams"
		11  	. "go/types"
		12  )
		13  
		14  func TestNewMethodSet(t *testing.T) {
		15  	type method struct {
		16  		name		 string
		17  		index		[]int
		18  		indirect bool
		19  	}
		20  
		21  	// Tests are expressed src -> methods, for simplifying the composite literal.
		22  	// Should be kept in sync with TestLookupFieldOrMethod.
		23  	tests := map[string][]method{
		24  		// Named types
		25  		"var a T; type T struct{}; func (T) f() {}":	 {{"f", []int{0}, false}},
		26  		"var a *T; type T struct{}; func (T) f() {}":	{{"f", []int{0}, true}},
		27  		"var a T; type T struct{}; func (*T) f() {}":	{},
		28  		"var a *T; type T struct{}; func (*T) f() {}": {{"f", []int{0}, true}},
		29  
		30  		// Interfaces
		31  		"var a T; type T interface{ f() }":													 {{"f", []int{0}, true}},
		32  		"var a T1; type ( T1 T2; T2 interface{ f() } )":							{{"f", []int{0}, true}},
		33  		"var a T1; type ( T1 interface{ T2 }; T2 interface{ f() } )": {{"f", []int{0}, true}},
		34  
		35  		// Embedding
		36  		"var a struct{ E }; type E interface{ f() }":						{{"f", []int{0, 0}, true}},
		37  		"var a *struct{ E }; type E interface{ f() }":					 {{"f", []int{0, 0}, true}},
		38  		"var a struct{ E }; type E struct{}; func (E) f() {}":	 {{"f", []int{0, 0}, false}},
		39  		"var a struct{ *E }; type E struct{}; func (E) f() {}":	{{"f", []int{0, 0}, true}},
		40  		"var a struct{ E }; type E struct{}; func (*E) f() {}":	{},
		41  		"var a struct{ *E }; type E struct{}; func (*E) f() {}": {{"f", []int{0, 0}, true}},
		42  
		43  		// collisions
		44  		"var a struct{ E1; *E2 }; type ( E1 interface{ f() }; E2 struct{ f int })":						{},
		45  		"var a struct{ E1; *E2 }; type ( E1 struct{ f int }; E2 struct{} ); func (E2) f() {}": {},
		46  	}
		47  
		48  	genericTests := map[string][]method{
		49  		// By convention, look up a in the scope of "g"
		50  		"type C interface{ f() }; func g[T C](a T){}":											 {{"f", []int{0}, true}},
		51  		"type C interface{ f() }; func g[T C]() { var a T; _ = a }":				 {{"f", []int{0}, true}},
		52  		"type C interface{ f() }; func g[T C]() { var a struct{T}; _ = a }": {{"f", []int{0, 0}, true}},
		53  
		54  		// Issue #45639.
		55  		"type C interface{ f() }; func g[T C]() { type Y T; var a Y; _ = a }": {},
		56  	}
		57  
		58  	check := func(src string, methods []method, generic bool) {
		59  		pkgName := "p"
		60  		if generic {
		61  			// The generic_ prefix causes pkgFor to allow generic code.
		62  			pkgName = "generic_p"
		63  		}
		64  		pkg, err := pkgFor("test", "package "+pkgName+";"+src, nil)
		65  		if err != nil {
		66  			t.Errorf("%s: incorrect test case: %s", src, err)
		67  			return
		68  		}
		69  
		70  		scope := pkg.Scope()
		71  		if generic {
		72  			fn := pkg.Scope().Lookup("g").(*Func)
		73  			scope = fn.Scope()
		74  		}
		75  		obj := scope.Lookup("a")
		76  		if obj == nil {
		77  			t.Errorf("%s: incorrect test case - no object a", src)
		78  			return
		79  		}
		80  
		81  		ms := NewMethodSet(obj.Type())
		82  		if got, want := ms.Len(), len(methods); got != want {
		83  			t.Errorf("%s: got %d methods, want %d", src, got, want)
		84  			return
		85  		}
		86  		for i, m := range methods {
		87  			sel := ms.At(i)
		88  			if got, want := sel.Obj().Name(), m.name; got != want {
		89  				t.Errorf("%s [method %d]: got name = %q at, want %q", src, i, got, want)
		90  			}
		91  			if got, want := sel.Index(), m.index; !sameSlice(got, want) {
		92  				t.Errorf("%s [method %d]: got index = %v, want %v", src, i, got, want)
		93  			}
		94  			if got, want := sel.Indirect(), m.indirect; got != want {
		95  				t.Errorf("%s [method %d]: got indirect = %v, want %v", src, i, got, want)
		96  			}
		97  		}
		98  	}
		99  
	 100  	for src, methods := range tests {
	 101  		check(src, methods, false)
	 102  	}
	 103  
	 104  	if typeparams.Enabled {
	 105  		for src, methods := range genericTests {
	 106  			check(src, methods, true)
	 107  		}
	 108  	}
	 109  }
	 110  

View as plain text