github.com/lovishpuri/go-40569/src@v0.0.0-20230519171745-f8623e7c56cf/go/types/issues_test.go (about)

     1  // Copyright 2013 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  // This file implements tests for various issues.
     6  
     7  package types_test
     8  
     9  import (
    10  	"fmt"
    11  	"go/ast"
    12  	"go/importer"
    13  	"go/token"
    14  	"internal/testenv"
    15  	"regexp"
    16  	"sort"
    17  	"strings"
    18  	"testing"
    19  
    20  	. "go/types"
    21  )
    22  
    23  func TestIssue5770(t *testing.T) {
    24  	_, err := typecheck(`package p; type S struct{T}`, nil, nil)
    25  	const want = "undefined: T"
    26  	if err == nil || !strings.Contains(err.Error(), want) {
    27  		t.Errorf("got: %v; want: %s", err, want)
    28  	}
    29  }
    30  
    31  func TestIssue5849(t *testing.T) {
    32  	src := `
    33  package p
    34  var (
    35  	s uint
    36  	_ = uint8(8)
    37  	_ = uint16(16) << s
    38  	_ = uint32(32 << s)
    39  	_ = uint64(64 << s + s)
    40  	_ = (interface{})("foo")
    41  	_ = (interface{})(nil)
    42  )`
    43  	types := make(map[ast.Expr]TypeAndValue)
    44  	mustTypecheck(src, nil, &Info{Types: types})
    45  
    46  	for x, tv := range types {
    47  		var want Type
    48  		switch x := x.(type) {
    49  		case *ast.BasicLit:
    50  			switch x.Value {
    51  			case `8`:
    52  				want = Typ[Uint8]
    53  			case `16`:
    54  				want = Typ[Uint16]
    55  			case `32`:
    56  				want = Typ[Uint32]
    57  			case `64`:
    58  				want = Typ[Uint] // because of "+ s", s is of type uint
    59  			case `"foo"`:
    60  				want = Typ[String]
    61  			}
    62  		case *ast.Ident:
    63  			if x.Name == "nil" {
    64  				want = Typ[UntypedNil]
    65  			}
    66  		}
    67  		if want != nil && !Identical(tv.Type, want) {
    68  			t.Errorf("got %s; want %s", tv.Type, want)
    69  		}
    70  	}
    71  }
    72  
    73  func TestIssue6413(t *testing.T) {
    74  	src := `
    75  package p
    76  func f() int {
    77  	defer f()
    78  	go f()
    79  	return 0
    80  }
    81  `
    82  	types := make(map[ast.Expr]TypeAndValue)
    83  	mustTypecheck(src, nil, &Info{Types: types})
    84  
    85  	want := Typ[Int]
    86  	n := 0
    87  	for x, tv := range types {
    88  		if _, ok := x.(*ast.CallExpr); ok {
    89  			if tv.Type != want {
    90  				t.Errorf("%s: got %s; want %s", fset.Position(x.Pos()), tv.Type, want)
    91  			}
    92  			n++
    93  		}
    94  	}
    95  
    96  	if n != 2 {
    97  		t.Errorf("got %d CallExprs; want 2", n)
    98  	}
    99  }
   100  
   101  func TestIssue7245(t *testing.T) {
   102  	src := `
   103  package p
   104  func (T) m() (res bool) { return }
   105  type T struct{} // receiver type after method declaration
   106  `
   107  	f := mustParse(fset, src)
   108  
   109  	var conf Config
   110  	defs := make(map[*ast.Ident]Object)
   111  	_, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs})
   112  	if err != nil {
   113  		t.Fatal(err)
   114  	}
   115  
   116  	m := f.Decls[0].(*ast.FuncDecl)
   117  	res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0)
   118  	res2 := defs[m.Type.Results.List[0].Names[0]].(*Var)
   119  
   120  	if res1 != res2 {
   121  		t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
   122  	}
   123  }
   124  
   125  // This tests that uses of existing vars on the LHS of an assignment
   126  // are Uses, not Defs; and also that the (illegal) use of a non-var on
   127  // the LHS of an assignment is a Use nonetheless.
   128  func TestIssue7827(t *testing.T) {
   129  	const src = `
   130  package p
   131  func _() {
   132  	const w = 1        // defs w
   133          x, y := 2, 3       // defs x, y
   134          w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
   135          _, _, _ = x, y, z  // uses x, y, z
   136  }
   137  `
   138  	// We need a specific fileset in this test below for positions.
   139  	// Cannot use typecheck helper.
   140  	fset := token.NewFileSet()
   141  	f := mustParse(fset, src)
   142  
   143  	const want = `L3 defs func p._()
   144  L4 defs const w untyped int
   145  L5 defs var x int
   146  L5 defs var y int
   147  L6 defs var z int
   148  L6 uses const w untyped int
   149  L6 uses var x int
   150  L7 uses var x int
   151  L7 uses var y int
   152  L7 uses var z int`
   153  
   154  	// don't abort at the first error
   155  	conf := Config{Error: func(err error) { t.Log(err) }}
   156  	defs := make(map[*ast.Ident]Object)
   157  	uses := make(map[*ast.Ident]Object)
   158  	_, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses})
   159  	if s := err.Error(); !strings.HasSuffix(s, "cannot assign to w") {
   160  		t.Errorf("Check: unexpected error: %s", s)
   161  	}
   162  
   163  	var facts []string
   164  	for id, obj := range defs {
   165  		if obj != nil {
   166  			fact := fmt.Sprintf("L%d defs %s", fset.Position(id.Pos()).Line, obj)
   167  			facts = append(facts, fact)
   168  		}
   169  	}
   170  	for id, obj := range uses {
   171  		fact := fmt.Sprintf("L%d uses %s", fset.Position(id.Pos()).Line, obj)
   172  		facts = append(facts, fact)
   173  	}
   174  	sort.Strings(facts)
   175  
   176  	got := strings.Join(facts, "\n")
   177  	if got != want {
   178  		t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
   179  	}
   180  }
   181  
   182  // This tests that the package associated with the types.Object.Pkg method
   183  // is the type's package independent of the order in which the imports are
   184  // listed in the sources src1, src2 below.
   185  // The actual issue is in go/internal/gcimporter which has a corresponding
   186  // test; we leave this test here to verify correct behavior at the go/types
   187  // level.
   188  func TestIssue13898(t *testing.T) {
   189  	testenv.MustHaveGoBuild(t)
   190  
   191  	const src0 = `
   192  package main
   193  
   194  import "go/types"
   195  
   196  func main() {
   197  	var info types.Info
   198  	for _, obj := range info.Uses {
   199  		_ = obj.Pkg()
   200  	}
   201  }
   202  `
   203  	// like src0, but also imports go/importer
   204  	const src1 = `
   205  package main
   206  
   207  import (
   208  	"go/types"
   209  	_ "go/importer"
   210  )
   211  
   212  func main() {
   213  	var info types.Info
   214  	for _, obj := range info.Uses {
   215  		_ = obj.Pkg()
   216  	}
   217  }
   218  `
   219  	// like src1 but with different import order
   220  	// (used to fail with this issue)
   221  	const src2 = `
   222  package main
   223  
   224  import (
   225  	_ "go/importer"
   226  	"go/types"
   227  )
   228  
   229  func main() {
   230  	var info types.Info
   231  	for _, obj := range info.Uses {
   232  		_ = obj.Pkg()
   233  	}
   234  }
   235  `
   236  	f := func(test, src string) {
   237  		info := &Info{Uses: make(map[*ast.Ident]Object)}
   238  		mustTypecheck(src, nil, info)
   239  
   240  		var pkg *Package
   241  		count := 0
   242  		for id, obj := range info.Uses {
   243  			if id.Name == "Pkg" {
   244  				pkg = obj.Pkg()
   245  				count++
   246  			}
   247  		}
   248  		if count != 1 {
   249  			t.Fatalf("%s: got %d entries named Pkg; want 1", test, count)
   250  		}
   251  		if pkg.Name() != "types" {
   252  			t.Fatalf("%s: got %v; want package types", test, pkg)
   253  		}
   254  	}
   255  
   256  	f("src0", src0)
   257  	f("src1", src1)
   258  	f("src2", src2)
   259  }
   260  
   261  func TestIssue22525(t *testing.T) {
   262  	const src = `package p; func f() { var a, b, c, d, e int }`
   263  
   264  	got := "\n"
   265  	conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
   266  	typecheck(src, &conf, nil) // do not crash
   267  	want := `
   268  p:1:27: a declared and not used
   269  p:1:30: b declared and not used
   270  p:1:33: c declared and not used
   271  p:1:36: d declared and not used
   272  p:1:39: e declared and not used
   273  `
   274  	if got != want {
   275  		t.Errorf("got: %swant: %s", got, want)
   276  	}
   277  }
   278  
   279  func TestIssue25627(t *testing.T) {
   280  	const prefix = `package p; import "unsafe"; type P *struct{}; type I interface{}; type T `
   281  	// The src strings (without prefix) are constructed such that the number of semicolons
   282  	// plus one corresponds to the number of fields expected in the respective struct.
   283  	for _, src := range []string{
   284  		`struct { x Missing }`,
   285  		`struct { Missing }`,
   286  		`struct { *Missing }`,
   287  		`struct { unsafe.Pointer }`,
   288  		`struct { P }`,
   289  		`struct { *I }`,
   290  		`struct { a int; b Missing; *Missing }`,
   291  	} {
   292  		f := mustParse(fset, prefix+src)
   293  
   294  		cfg := Config{Importer: importer.Default(), Error: func(err error) {}}
   295  		info := &Info{Types: make(map[ast.Expr]TypeAndValue)}
   296  		_, err := cfg.Check(f.Name.Name, fset, []*ast.File{f}, info)
   297  		if err != nil {
   298  			if _, ok := err.(Error); !ok {
   299  				t.Fatal(err)
   300  			}
   301  		}
   302  
   303  		ast.Inspect(f, func(n ast.Node) bool {
   304  			if spec, _ := n.(*ast.TypeSpec); spec != nil {
   305  				if tv, ok := info.Types[spec.Type]; ok && spec.Name.Name == "T" {
   306  					want := strings.Count(src, ";") + 1
   307  					if got := tv.Type.(*Struct).NumFields(); got != want {
   308  						t.Errorf("%s: got %d fields; want %d", src, got, want)
   309  					}
   310  				}
   311  			}
   312  			return true
   313  		})
   314  	}
   315  }
   316  
   317  func TestIssue28005(t *testing.T) {
   318  	// method names must match defining interface name for this test
   319  	// (see last comment in this function)
   320  	sources := [...]string{
   321  		"package p; type A interface{ A() }",
   322  		"package p; type B interface{ B() }",
   323  		"package p; type X interface{ A; B }",
   324  	}
   325  
   326  	// compute original file ASTs
   327  	var orig [len(sources)]*ast.File
   328  	for i, src := range sources {
   329  		orig[i] = mustParse(fset, src)
   330  	}
   331  
   332  	// run the test for all order permutations of the incoming files
   333  	for _, perm := range [][len(sources)]int{
   334  		{0, 1, 2},
   335  		{0, 2, 1},
   336  		{1, 0, 2},
   337  		{1, 2, 0},
   338  		{2, 0, 1},
   339  		{2, 1, 0},
   340  	} {
   341  		// create file order permutation
   342  		files := make([]*ast.File, len(sources))
   343  		for i := range perm {
   344  			files[i] = orig[perm[i]]
   345  		}
   346  
   347  		// type-check package with given file order permutation
   348  		var conf Config
   349  		info := &Info{Defs: make(map[*ast.Ident]Object)}
   350  		_, err := conf.Check("", fset, files, info)
   351  		if err != nil {
   352  			t.Fatal(err)
   353  		}
   354  
   355  		// look for interface object X
   356  		var obj Object
   357  		for name, def := range info.Defs {
   358  			if name.Name == "X" {
   359  				obj = def
   360  				break
   361  			}
   362  		}
   363  		if obj == nil {
   364  			t.Fatal("object X not found")
   365  		}
   366  		iface := obj.Type().Underlying().(*Interface) // object X must be an interface
   367  
   368  		// Each iface method m is embedded; and m's receiver base type name
   369  		// must match the method's name per the choice in the source file.
   370  		for i := 0; i < iface.NumMethods(); i++ {
   371  			m := iface.Method(i)
   372  			recvName := m.Type().(*Signature).Recv().Type().(*Named).Obj().Name()
   373  			if recvName != m.Name() {
   374  				t.Errorf("perm %v: got recv %s; want %s", perm, recvName, m.Name())
   375  			}
   376  		}
   377  	}
   378  }
   379  
   380  func TestIssue28282(t *testing.T) {
   381  	// create type interface { error }
   382  	et := Universe.Lookup("error").Type()
   383  	it := NewInterfaceType(nil, []Type{et})
   384  	it.Complete()
   385  	// verify that after completing the interface, the embedded method remains unchanged
   386  	want := et.Underlying().(*Interface).Method(0)
   387  	got := it.Method(0)
   388  	if got != want {
   389  		t.Fatalf("%s.Method(0): got %q (%p); want %q (%p)", it, got, got, want, want)
   390  	}
   391  	// verify that lookup finds the same method in both interfaces (redundant check)
   392  	obj, _, _ := LookupFieldOrMethod(et, false, nil, "Error")
   393  	if obj != want {
   394  		t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", et, obj, obj, want, want)
   395  	}
   396  	obj, _, _ = LookupFieldOrMethod(it, false, nil, "Error")
   397  	if obj != want {
   398  		t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", it, obj, obj, want, want)
   399  	}
   400  }
   401  
   402  func TestIssue29029(t *testing.T) {
   403  	f1 := mustParse(fset, `package p; type A interface { M() }`)
   404  	f2 := mustParse(fset, `package p; var B interface { A }`)
   405  
   406  	// printInfo prints the *Func definitions recorded in info, one *Func per line.
   407  	printInfo := func(info *Info) string {
   408  		var buf strings.Builder
   409  		for _, obj := range info.Defs {
   410  			if fn, ok := obj.(*Func); ok {
   411  				fmt.Fprintln(&buf, fn)
   412  			}
   413  		}
   414  		return buf.String()
   415  	}
   416  
   417  	// The *Func (method) definitions for package p must be the same
   418  	// independent on whether f1 and f2 are type-checked together, or
   419  	// incrementally.
   420  
   421  	// type-check together
   422  	var conf Config
   423  	info := &Info{Defs: make(map[*ast.Ident]Object)}
   424  	check := NewChecker(&conf, fset, NewPackage("", "p"), info)
   425  	if err := check.Files([]*ast.File{f1, f2}); err != nil {
   426  		t.Fatal(err)
   427  	}
   428  	want := printInfo(info)
   429  
   430  	// type-check incrementally
   431  	info = &Info{Defs: make(map[*ast.Ident]Object)}
   432  	check = NewChecker(&conf, fset, NewPackage("", "p"), info)
   433  	if err := check.Files([]*ast.File{f1}); err != nil {
   434  		t.Fatal(err)
   435  	}
   436  	if err := check.Files([]*ast.File{f2}); err != nil {
   437  		t.Fatal(err)
   438  	}
   439  	got := printInfo(info)
   440  
   441  	if got != want {
   442  		t.Errorf("\ngot : %swant: %s", got, want)
   443  	}
   444  }
   445  
   446  func TestIssue34151(t *testing.T) {
   447  	const asrc = `package a; type I interface{ M() }; type T struct { F interface { I } }`
   448  	const bsrc = `package b; import "a"; type T struct { F interface { a.I } }; var _ = a.T(T{})`
   449  
   450  	a := mustTypecheck(asrc, nil, nil)
   451  
   452  	conf := Config{Importer: importHelper{pkg: a}}
   453  	mustTypecheck(bsrc, &conf, nil)
   454  }
   455  
   456  type importHelper struct {
   457  	pkg      *Package
   458  	fallback Importer
   459  }
   460  
   461  func (h importHelper) Import(path string) (*Package, error) {
   462  	if path == h.pkg.Path() {
   463  		return h.pkg, nil
   464  	}
   465  	if h.fallback == nil {
   466  		return nil, fmt.Errorf("got package path %q; want %q", path, h.pkg.Path())
   467  	}
   468  	return h.fallback.Import(path)
   469  }
   470  
   471  // TestIssue34921 verifies that we don't update an imported type's underlying
   472  // type when resolving an underlying type. Specifically, when determining the
   473  // underlying type of b.T (which is the underlying type of a.T, which is int)
   474  // we must not set the underlying type of a.T again since that would lead to
   475  // a race condition if package b is imported elsewhere, in a package that is
   476  // concurrently type-checked.
   477  func TestIssue34921(t *testing.T) {
   478  	defer func() {
   479  		if r := recover(); r != nil {
   480  			t.Error(r)
   481  		}
   482  	}()
   483  
   484  	var sources = []string{
   485  		`package a; type T int`,
   486  		`package b; import "a"; type T a.T`,
   487  	}
   488  
   489  	var pkg *Package
   490  	for _, src := range sources {
   491  		conf := Config{Importer: importHelper{pkg: pkg}}
   492  		pkg = mustTypecheck(src, &conf, nil) // pkg imported by the next package in this test
   493  	}
   494  }
   495  
   496  func TestIssue43088(t *testing.T) {
   497  	// type T1 struct {
   498  	//         _ T2
   499  	// }
   500  	//
   501  	// type T2 struct {
   502  	//         _ struct {
   503  	//                 _ T2
   504  	//         }
   505  	// }
   506  	n1 := NewTypeName(nopos, nil, "T1", nil)
   507  	T1 := NewNamed(n1, nil, nil)
   508  	n2 := NewTypeName(nopos, nil, "T2", nil)
   509  	T2 := NewNamed(n2, nil, nil)
   510  	s1 := NewStruct([]*Var{NewField(nopos, nil, "_", T2, false)}, nil)
   511  	T1.SetUnderlying(s1)
   512  	s2 := NewStruct([]*Var{NewField(nopos, nil, "_", T2, false)}, nil)
   513  	s3 := NewStruct([]*Var{NewField(nopos, nil, "_", s2, false)}, nil)
   514  	T2.SetUnderlying(s3)
   515  
   516  	// These calls must terminate (no endless recursion).
   517  	Comparable(T1)
   518  	Comparable(T2)
   519  }
   520  
   521  func TestIssue44515(t *testing.T) {
   522  	typ := Unsafe.Scope().Lookup("Pointer").Type()
   523  
   524  	got := TypeString(typ, nil)
   525  	want := "unsafe.Pointer"
   526  	if got != want {
   527  		t.Errorf("got %q; want %q", got, want)
   528  	}
   529  
   530  	qf := func(pkg *Package) string {
   531  		if pkg == Unsafe {
   532  			return "foo"
   533  		}
   534  		return ""
   535  	}
   536  	got = TypeString(typ, qf)
   537  	want = "foo.Pointer"
   538  	if got != want {
   539  		t.Errorf("got %q; want %q", got, want)
   540  	}
   541  }
   542  
   543  func TestIssue43124(t *testing.T) {
   544  	// TODO(rFindley) move this to testdata by enhancing support for importing.
   545  
   546  	testenv.MustHaveGoBuild(t) // The go command is needed for the importer to determine the locations of stdlib .a files.
   547  
   548  	// All involved packages have the same name (template). Error messages should
   549  	// disambiguate between text/template and html/template by printing the full
   550  	// path.
   551  	const (
   552  		asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
   553  		bsrc = `
   554  package b
   555  
   556  import (
   557  	"a"
   558  	"html/template"
   559  )
   560  
   561  func _() {
   562  	// Packages should be fully qualified when there is ambiguity within the
   563  	// error string itself.
   564  	a.F(template /* ERRORx "cannot use.*html/template.* as .*text/template" */ .Template{})
   565  }
   566  `
   567  		csrc = `
   568  package c
   569  
   570  import (
   571  	"a"
   572  	"fmt"
   573  	"html/template"
   574  )
   575  
   576  // go.dev/issue/46905: make sure template is not the first package qualified.
   577  var _ fmt.Stringer = 1 // ERRORx "cannot use 1.*as fmt\\.Stringer"
   578  
   579  // Packages should be fully qualified when there is ambiguity in reachable
   580  // packages. In this case both a (and for that matter html/template) import
   581  // text/template.
   582  func _() { a.G(template /* ERRORx "cannot use .*html/template.*Template" */ .Template{}) }
   583  `
   584  
   585  		tsrc = `
   586  package template
   587  
   588  import "text/template"
   589  
   590  type T int
   591  
   592  // Verify that the current package name also causes disambiguation.
   593  var _ T = template /* ERRORx "cannot use.*text/template.* as T value" */.Template{}
   594  `
   595  	)
   596  
   597  	a := mustTypecheck(asrc, nil, nil)
   598  	imp := importHelper{pkg: a, fallback: importer.Default()}
   599  
   600  	testFiles(t, nil, []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, imp)
   601  	testFiles(t, nil, []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp)
   602  	testFiles(t, nil, []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp)
   603  }
   604  
   605  func TestIssue50646(t *testing.T) {
   606  	anyType := Universe.Lookup("any").Type()
   607  	comparableType := Universe.Lookup("comparable").Type()
   608  
   609  	if !Comparable(anyType) {
   610  		t.Error("any is not a comparable type")
   611  	}
   612  	if !Comparable(comparableType) {
   613  		t.Error("comparable is not a comparable type")
   614  	}
   615  
   616  	if Implements(anyType, comparableType.Underlying().(*Interface)) {
   617  		t.Error("any implements comparable")
   618  	}
   619  	if !Implements(comparableType, anyType.(*Interface)) {
   620  		t.Error("comparable does not implement any")
   621  	}
   622  
   623  	if AssignableTo(anyType, comparableType) {
   624  		t.Error("any assignable to comparable")
   625  	}
   626  	if !AssignableTo(comparableType, anyType) {
   627  		t.Error("comparable not assignable to any")
   628  	}
   629  }
   630  
   631  func TestIssue55030(t *testing.T) {
   632  	// makeSig makes the signature func(typ...)
   633  	makeSig := func(typ Type) {
   634  		par := NewVar(nopos, nil, "", typ)
   635  		params := NewTuple(par)
   636  		NewSignatureType(nil, nil, nil, params, nil, true)
   637  	}
   638  
   639  	// makeSig must not panic for the following (example) types:
   640  	// []int
   641  	makeSig(NewSlice(Typ[Int]))
   642  
   643  	// string
   644  	makeSig(Typ[String])
   645  
   646  	// P where P's core type is string
   647  	{
   648  		P := NewTypeName(nopos, nil, "P", nil) // [P string]
   649  		makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
   650  	}
   651  
   652  	// P where P's core type is an (unnamed) slice
   653  	{
   654  		P := NewTypeName(nopos, nil, "P", nil) // [P []int]
   655  		makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
   656  	}
   657  
   658  	// P where P's core type is bytestring (i.e., string or []byte)
   659  	{
   660  		t1 := NewTerm(true, Typ[String])          // ~string
   661  		t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
   662  		u := NewUnion([]*Term{t1, t2})            // ~string | []byte
   663  		P := NewTypeName(nopos, nil, "P", nil)    // [P ~string | []byte]
   664  		makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
   665  	}
   666  }
   667  
   668  func TestIssue51093(t *testing.T) {
   669  	// Each test stands for a conversion of the form P(val)
   670  	// where P is a type parameter with typ as constraint.
   671  	// The test ensures that P(val) has the correct type P
   672  	// and is not a constant.
   673  	var tests = []struct {
   674  		typ string
   675  		val string
   676  	}{
   677  		{"bool", "false"},
   678  		{"int", "-1"},
   679  		{"uint", "1.0"},
   680  		{"rune", "'a'"},
   681  		{"float64", "3.5"},
   682  		{"complex64", "1.25"},
   683  		{"string", "\"foo\""},
   684  
   685  		// some more complex constraints
   686  		{"~byte", "1"},
   687  		{"~int | ~float64 | complex128", "1"},
   688  		{"~uint64 | ~rune", "'X'"},
   689  	}
   690  
   691  	for _, test := range tests {
   692  		src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val)
   693  		types := make(map[ast.Expr]TypeAndValue)
   694  		mustTypecheck(src, nil, &Info{Types: types})
   695  
   696  		var n int
   697  		for x, tv := range types {
   698  			if x, _ := x.(*ast.CallExpr); x != nil {
   699  				// there must be exactly one CallExpr which is the P(val) conversion
   700  				n++
   701  				tpar, _ := tv.Type.(*TypeParam)
   702  				if tpar == nil {
   703  					t.Fatalf("%s: got type %s, want type parameter", ExprString(x), tv.Type)
   704  				}
   705  				if name := tpar.Obj().Name(); name != "P" {
   706  					t.Fatalf("%s: got type parameter name %s, want P", ExprString(x), name)
   707  				}
   708  				// P(val) must not be constant
   709  				if tv.Value != nil {
   710  					t.Errorf("%s: got constant value %s (%s), want no constant", ExprString(x), tv.Value, tv.Value.String())
   711  				}
   712  			}
   713  		}
   714  
   715  		if n != 1 {
   716  			t.Fatalf("%s: got %d CallExpr nodes; want 1", src, 1)
   717  		}
   718  	}
   719  }
   720  
   721  func TestIssue54258(t *testing.T) {
   722  
   723  	tests := []struct{ main, b, want string }{
   724  		{ //---------------------------------------------------------------
   725  			`package main
   726  import "b"
   727  type I0 interface {
   728  	M0(w struct{ f string })
   729  }
   730  var _ I0 = b.S{}
   731  `,
   732  			`package b
   733  type S struct{}
   734  func (S) M0(struct{ f string }) {}
   735  `,
   736  			`6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I0 value in variable declaration: b[.]S does not implement I0 [(]wrong type for method M0[)]
   737  .*have M0[(]struct{f string /[*] package b [*]/ }[)]
   738  .*want M0[(]struct{f string /[*] package main [*]/ }[)]`},
   739  
   740  		{ //---------------------------------------------------------------
   741  			`package main
   742  import "b"
   743  type I1 interface {
   744  	M1(struct{ string })
   745  }
   746  var _ I1 = b.S{}
   747  `,
   748  			`package b
   749  type S struct{}
   750  func (S) M1(struct{ string }) {}
   751  `,
   752  			`6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I1 value in variable declaration: b[.]S does not implement I1 [(]wrong type for method M1[)]
   753  .*have M1[(]struct{string /[*] package b [*]/ }[)]
   754  .*want M1[(]struct{string /[*] package main [*]/ }[)]`},
   755  
   756  		{ //---------------------------------------------------------------
   757  			`package main
   758  import "b"
   759  type I2 interface {
   760  	M2(y struct{ f struct{ f string } })
   761  }
   762  var _ I2 = b.S{}
   763  `,
   764  			`package b
   765  type S struct{}
   766  func (S) M2(struct{ f struct{ f string } }) {}
   767  `,
   768  			`6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I2 value in variable declaration: b[.]S does not implement I2 [(]wrong type for method M2[)]
   769  .*have M2[(]struct{f struct{f string} /[*] package b [*]/ }[)]
   770  .*want M2[(]struct{f struct{f string} /[*] package main [*]/ }[)]`},
   771  
   772  		{ //---------------------------------------------------------------
   773  			`package main
   774  import "b"
   775  type I3 interface {
   776  	M3(z struct{ F struct{ f string } })
   777  }
   778  var _ I3 = b.S{}
   779  `,
   780  			`package b
   781  type S struct{}
   782  func (S) M3(struct{ F struct{ f string } }) {}
   783  `,
   784  			`6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I3 value in variable declaration: b[.]S does not implement I3 [(]wrong type for method M3[)]
   785  .*have M3[(]struct{F struct{f string /[*] package b [*]/ }}[)]
   786  .*want M3[(]struct{F struct{f string /[*] package main [*]/ }}[)]`},
   787  
   788  		{ //---------------------------------------------------------------
   789  			`package main
   790  import "b"
   791  type I4 interface {
   792  	M4(_ struct { *string })
   793  }
   794  var _ I4 = b.S{}
   795  `,
   796  			`package b
   797  type S struct{}
   798  func (S) M4(struct { *string }) {}
   799  `,
   800  			`6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I4 value in variable declaration: b[.]S does not implement I4 [(]wrong type for method M4[)]
   801  .*have M4[(]struct{[*]string /[*] package b [*]/ }[)]
   802  .*want M4[(]struct{[*]string /[*] package main [*]/ }[)]`},
   803  
   804  		{ //---------------------------------------------------------------
   805  			`package main
   806  import "b"
   807  type t struct{ A int }
   808  type I5 interface {
   809  	M5(_ struct {b.S;t})
   810  }
   811  var _ I5 = b.S{}
   812  `,
   813  			`package b
   814  type S struct{}
   815  type t struct{ A int }
   816  func (S) M5(struct {S;t}) {}
   817  `,
   818  			`7:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I5 value in variable declaration: b[.]S does not implement I5 [(]wrong type for method M5[)]
   819  .*have M5[(]struct{b[.]S; b[.]t}[)]
   820  .*want M5[(]struct{b[.]S; t}[)]`},
   821  	}
   822  
   823  	fset := token.NewFileSet()
   824  	test := func(main, b, want string) {
   825  		re := regexp.MustCompile(want)
   826  		bpkg := mustTypecheck(b, nil, nil)
   827  		mast := mustParse(fset, main)
   828  		conf := Config{Importer: importHelper{pkg: bpkg}}
   829  		_, err := conf.Check(mast.Name.Name, fset, []*ast.File{mast}, nil)
   830  		if err == nil {
   831  			t.Error("Expected failure, but it did not")
   832  		} else if got := err.Error(); !re.MatchString(got) {
   833  			t.Errorf("Wanted match for\n\t%s\n but got\n\t%s", want, got)
   834  		} else if testing.Verbose() {
   835  			t.Logf("Saw expected\n\t%s", err.Error())
   836  		}
   837  	}
   838  	for _, t := range tests {
   839  		test(t.main, t.b, t.want)
   840  	}
   841  }