issues_test.go raw

   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/parser"
  13  	"go/token"
  14  	"internal/testenv"
  15  	"regexp"
  16  	"slices"
  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).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  	slices.Sort(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 := "\n" +
 268  		"p:1:27: declared and not used: a\n" +
 269  		"p:1:30: declared and not used: b\n" +
 270  		"p:1:33: declared and not used: c\n" +
 271  		"p:1:36: declared and not used: d\n" +
 272  		"p:1:39: declared and not used: e\n"
 273  	if got != want {
 274  		t.Errorf("got: %swant: %s", got, want)
 275  	}
 276  }
 277  
 278  func TestIssue25627(t *testing.T) {
 279  	const prefix = `package p; import "unsafe"; type P *struct{}; type I interface{}; type T `
 280  	// The src strings (without prefix) are constructed such that the number of semicolons
 281  	// plus one corresponds to the number of fields expected in the respective struct.
 282  	for _, src := range []string{
 283  		`struct { x Missing }`,
 284  		`struct { Missing }`,
 285  		`struct { *Missing }`,
 286  		`struct { unsafe.Pointer }`,
 287  		`struct { P }`,
 288  		`struct { *I }`,
 289  		`struct { a int; b Missing; *Missing }`,
 290  	} {
 291  		f := mustParse(fset, prefix+src)
 292  
 293  		cfg := Config{Importer: defaultImporter(fset), Error: func(err error) {}}
 294  		info := &Info{Types: make(map[ast.Expr]TypeAndValue)}
 295  		_, err := cfg.Check(f.Name.Name, fset, []*ast.File{f}, info)
 296  		if err != nil {
 297  			if _, ok := err.(Error); !ok {
 298  				t.Fatal(err)
 299  			}
 300  		}
 301  
 302  		ast.Inspect(f, func(n ast.Node) bool {
 303  			if spec, _ := n.(*ast.TypeSpec); spec != nil {
 304  				if tv, ok := info.Types[spec.Type]; ok && spec.Name.Name == "T" {
 305  					want := strings.Count(src, ";") + 1
 306  					if got := tv.Type.(*Struct).NumFields(); got != want {
 307  						t.Errorf("%s: got %d fields; want %d", src, got, want)
 308  					}
 309  				}
 310  			}
 311  			return true
 312  		})
 313  	}
 314  }
 315  
 316  func TestIssue28005(t *testing.T) {
 317  	// method names must match defining interface name for this test
 318  	// (see last comment in this function)
 319  	sources := [...]string{
 320  		"package p; type A interface{ A() }",
 321  		"package p; type B interface{ B() }",
 322  		"package p; type X interface{ A; B }",
 323  	}
 324  
 325  	// compute original file ASTs
 326  	var orig [len(sources)]*ast.File
 327  	for i, src := range sources {
 328  		orig[i] = mustParse(fset, src)
 329  	}
 330  
 331  	// run the test for all order permutations of the incoming files
 332  	for _, perm := range [][len(sources)]int{
 333  		{0, 1, 2},
 334  		{0, 2, 1},
 335  		{1, 0, 2},
 336  		{1, 2, 0},
 337  		{2, 0, 1},
 338  		{2, 1, 0},
 339  	} {
 340  		// create file order permutation
 341  		files := make([]*ast.File, len(sources))
 342  		for i := range perm {
 343  			files[i] = orig[perm[i]]
 344  		}
 345  
 346  		// type-check package with given file order permutation
 347  		var conf Config
 348  		info := &Info{Defs: make(map[*ast.Ident]Object)}
 349  		_, err := conf.Check("", fset, files, info)
 350  		if err != nil {
 351  			t.Fatal(err)
 352  		}
 353  
 354  		// look for interface object X
 355  		var obj Object
 356  		for name, def := range info.Defs {
 357  			if name.Name == "X" {
 358  				obj = def
 359  				break
 360  			}
 361  		}
 362  		if obj == nil {
 363  			t.Fatal("object X not found")
 364  		}
 365  		iface := obj.Type().Underlying().(*Interface) // object X must be an interface
 366  
 367  		// Each iface method m is embedded; and m's receiver base type name
 368  		// must match the method's name per the choice in the source file.
 369  		for i := 0; i < iface.NumMethods(); i++ {
 370  			m := iface.Method(i)
 371  			recvName := m.Signature().Recv().Type().(*Named).Obj().Name()
 372  			if recvName != m.Name() {
 373  				t.Errorf("perm %v: got recv %s; want %s", perm, recvName, m.Name())
 374  			}
 375  		}
 376  	}
 377  }
 378  
 379  func TestIssue28282(t *testing.T) {
 380  	// create type interface { error }
 381  	et := Universe.Lookup("error").Type()
 382  	it := NewInterfaceType(nil, []Type{et})
 383  	it.Complete()
 384  	// verify that after completing the interface, the embedded method remains unchanged
 385  	want := et.Underlying().(*Interface).Method(0)
 386  	got := it.Method(0)
 387  	if got != want {
 388  		t.Fatalf("%s.Method(0): got %q (%p); want %q (%p)", it, got, got, want, want)
 389  	}
 390  	// verify that lookup finds the same method in both interfaces (redundant check)
 391  	obj, _, _ := LookupFieldOrMethod(et, false, nil, "Error")
 392  	if obj != want {
 393  		t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", et, obj, obj, want, want)
 394  	}
 395  	obj, _, _ = LookupFieldOrMethod(it, false, nil, "Error")
 396  	if obj != want {
 397  		t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", it, obj, obj, want, want)
 398  	}
 399  }
 400  
 401  func TestIssue29029(t *testing.T) {
 402  	f1 := mustParse(fset, `package p; type A interface { M() }`)
 403  	f2 := mustParse(fset, `package p; var B interface { A }`)
 404  
 405  	// printInfo prints the *Func definitions recorded in info, one *Func per line.
 406  	printInfo := func(info *Info) string {
 407  		var buf strings.Builder
 408  		for _, obj := range info.Defs {
 409  			if fn, ok := obj.(*Func); ok {
 410  				fmt.Fprintln(&buf, fn)
 411  			}
 412  		}
 413  		return buf.String()
 414  	}
 415  
 416  	// The *Func (method) definitions for package p must be the same
 417  	// independent on whether f1 and f2 are type-checked together, or
 418  	// incrementally.
 419  
 420  	// type-check together
 421  	var conf Config
 422  	info := &Info{Defs: make(map[*ast.Ident]Object)}
 423  	check := NewChecker(&conf, fset, NewPackage("", "p"), info)
 424  	if err := check.Files([]*ast.File{f1, f2}); err != nil {
 425  		t.Fatal(err)
 426  	}
 427  	want := printInfo(info)
 428  
 429  	// type-check incrementally
 430  	info = &Info{Defs: make(map[*ast.Ident]Object)}
 431  	check = NewChecker(&conf, fset, NewPackage("", "p"), info)
 432  	if err := check.Files([]*ast.File{f1}); err != nil {
 433  		t.Fatal(err)
 434  	}
 435  	if err := check.Files([]*ast.File{f2}); err != nil {
 436  		t.Fatal(err)
 437  	}
 438  	got := printInfo(info)
 439  
 440  	if got != want {
 441  		t.Errorf("\ngot : %swant: %s", got, want)
 442  	}
 443  }
 444  
 445  func TestIssue34151(t *testing.T) {
 446  	const asrc = `package a; type I interface{ M() }; type T struct { F interface { I } }`
 447  	const bsrc = `package b; import "a"; type T struct { F interface { a.I } }; var _ = a.T(T{})`
 448  
 449  	a := mustTypecheck(asrc, nil, nil)
 450  
 451  	conf := Config{Importer: importHelper{pkg: a}}
 452  	mustTypecheck(bsrc, &conf, nil)
 453  }
 454  
 455  type importHelper struct {
 456  	pkg      *Package
 457  	fallback Importer
 458  }
 459  
 460  func (h importHelper) Import(path string) (*Package, error) {
 461  	if path == h.pkg.Path() {
 462  		return h.pkg, nil
 463  	}
 464  	if h.fallback == nil {
 465  		return nil, fmt.Errorf("got package path %q; want %q", path, h.pkg.Path())
 466  	}
 467  	return h.fallback.Import(path)
 468  }
 469  
 470  // TestIssue34921 verifies that we don't update an imported type's underlying
 471  // type when resolving an underlying type. Specifically, when determining the
 472  // underlying type of b.T (which is the underlying type of a.T, which is int)
 473  // we must not set the underlying type of a.T again since that would lead to
 474  // a race condition if package b is imported elsewhere, in a package that is
 475  // concurrently type-checked.
 476  func TestIssue34921(t *testing.T) {
 477  	defer func() {
 478  		if r := recover(); r != nil {
 479  			t.Error(r)
 480  		}
 481  	}()
 482  
 483  	var sources = []string{
 484  		`package a; type T int`,
 485  		`package b; import "a"; type T a.T`,
 486  	}
 487  
 488  	var pkg *Package
 489  	for _, src := range sources {
 490  		conf := Config{Importer: importHelper{pkg: pkg}}
 491  		pkg = mustTypecheck(src, &conf, nil) // pkg imported by the next package in this test
 492  	}
 493  }
 494  
 495  func TestIssue43088(t *testing.T) {
 496  	// type T1 struct {
 497  	//         _ T2
 498  	// }
 499  	//
 500  	// type T2 struct {
 501  	//         _ struct {
 502  	//                 _ T2
 503  	//         }
 504  	// }
 505  	n1 := NewTypeName(nopos, nil, "T1", nil)
 506  	T1 := NewNamed(n1, nil, nil)
 507  	n2 := NewTypeName(nopos, nil, "T2", nil)
 508  	T2 := NewNamed(n2, nil, nil)
 509  	s1 := NewStruct([]*Var{NewField(nopos, nil, "_", T2, false)}, nil)
 510  	T1.SetUnderlying(s1)
 511  	s2 := NewStruct([]*Var{NewField(nopos, nil, "_", T2, false)}, nil)
 512  	s3 := NewStruct([]*Var{NewField(nopos, nil, "_", s2, false)}, nil)
 513  	T2.SetUnderlying(s3)
 514  
 515  	// These calls must terminate (no endless recursion).
 516  	Comparable(T1)
 517  	Comparable(T2)
 518  }
 519  
 520  func TestIssue44515(t *testing.T) {
 521  	typ := Unsafe.Scope().Lookup("Pointer").Type()
 522  
 523  	got := TypeString(typ, nil)
 524  	want := "unsafe.Pointer"
 525  	if got != want {
 526  		t.Errorf("got %q; want %q", got, want)
 527  	}
 528  
 529  	qf := func(pkg *Package) string {
 530  		if pkg == Unsafe {
 531  			return "foo"
 532  		}
 533  		return ""
 534  	}
 535  	got = TypeString(typ, qf)
 536  	want = "foo.Pointer"
 537  	if got != want {
 538  		t.Errorf("got %q; want %q", got, want)
 539  	}
 540  }
 541  
 542  func TestIssue43124(t *testing.T) {
 543  	// TODO(rFindley) move this to testdata by enhancing support for importing.
 544  
 545  	testenv.MustHaveGoBuild(t) // The go command is needed for the importer to determine the locations of stdlib .a files.
 546  
 547  	// All involved packages have the same name (template). Error messages should
 548  	// disambiguate between text/template and html/template by printing the full
 549  	// path.
 550  	const (
 551  		asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
 552  		bsrc = `
 553  package b
 554  
 555  import (
 556  	"a"
 557  	"html/template"
 558  )
 559  
 560  func _() {
 561  	// Packages should be fully qualified when there is ambiguity within the
 562  	// error string itself.
 563  	a.F(template /* ERRORx "cannot use.*html/template.* as .*text/template" */ .Template{})
 564  }
 565  `
 566  		csrc = `
 567  package c
 568  
 569  import (
 570  	"a"
 571  	"fmt"
 572  	"html/template"
 573  )
 574  
 575  // go.dev/issue/46905: make sure template is not the first package qualified.
 576  var _ fmt.Stringer = 1 // ERRORx "cannot use 1.*as fmt\\.Stringer"
 577  
 578  // Packages should be fully qualified when there is ambiguity in reachable
 579  // packages. In this case both a (and for that matter html/template) import
 580  // text/template.
 581  func _() { a.G(template /* ERRORx "cannot use .*html/template.*Template" */ .Template{}) }
 582  `
 583  
 584  		tsrc = `
 585  package template
 586  
 587  import "text/template"
 588  
 589  type T int
 590  
 591  // Verify that the current package name also causes disambiguation.
 592  var _ T = template /* ERRORx "cannot use.*text/template.* as T value" */.Template{}
 593  `
 594  	)
 595  
 596  	a := mustTypecheck(asrc, nil, nil)
 597  	imp := importHelper{
 598  		pkg: a,
 599  		// TODO(adonovan): use same FileSet as mustTypecheck.
 600  		fallback: defaultImporter(token.NewFileSet()),
 601  	}
 602  
 603  	withImporter := func(cfg *Config) {
 604  		cfg.Importer = imp
 605  	}
 606  
 607  	testFiles(t, []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, withImporter)
 608  	testFiles(t, []string{"c.go"}, [][]byte{[]byte(csrc)}, false, withImporter)
 609  	testFiles(t, []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, withImporter)
 610  }
 611  
 612  func TestIssue50646(t *testing.T) {
 613  	anyType := Universe.Lookup("any").Type().Underlying()
 614  	comparableType := Universe.Lookup("comparable").Type()
 615  
 616  	if !Comparable(anyType) {
 617  		t.Error("any is not a comparable type")
 618  	}
 619  	if !Comparable(comparableType) {
 620  		t.Error("comparable is not a comparable type")
 621  	}
 622  
 623  	if Implements(anyType, comparableType.Underlying().(*Interface)) {
 624  		t.Error("any implements comparable")
 625  	}
 626  	if !Implements(comparableType, anyType.(*Interface)) {
 627  		t.Error("comparable does not implement any")
 628  	}
 629  
 630  	if AssignableTo(anyType, comparableType) {
 631  		t.Error("any assignable to comparable")
 632  	}
 633  	if !AssignableTo(comparableType, anyType) {
 634  		t.Error("comparable not assignable to any")
 635  	}
 636  }
 637  
 638  func TestIssue55030(t *testing.T) {
 639  	// makeSig makes the signature func(typ...)
 640  	// If valid is not set, making that signature is expected to panic.
 641  	makeSig := func(typ Type, valid bool) {
 642  		if !valid {
 643  			defer func() {
 644  				if recover() == nil {
 645  					panic("NewSignatureType panic expected")
 646  				}
 647  			}()
 648  		}
 649  		par := NewParam(nopos, nil, "", typ)
 650  		params := NewTuple(par)
 651  		NewSignatureType(nil, nil, nil, params, nil, true)
 652  	}
 653  
 654  	// makeSig must not panic for the following (example) types:
 655  	// []int
 656  	makeSig(NewSlice(Typ[Int]), true)
 657  
 658  	// string
 659  	makeSig(Typ[String], true)
 660  
 661  	// P where P's common underlying type is string
 662  	{
 663  		P := NewTypeName(nopos, nil, "P", nil) // [P string]
 664  		makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})), true)
 665  	}
 666  
 667  	// P where P's common underlying type is an (unnamed) slice
 668  	{
 669  		P := NewTypeName(nopos, nil, "P", nil) // [P []int]
 670  		makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})), true)
 671  	}
 672  
 673  	// P where P's type set contains strings and []byte
 674  	{
 675  		t1 := NewTerm(true, Typ[String])          // ~string
 676  		t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
 677  		u := NewUnion([]*Term{t1, t2})            // ~string | []byte
 678  		P := NewTypeName(nopos, nil, "P", nil)    // [P ~string | []byte]
 679  		makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})), true)
 680  	}
 681  
 682  	// makeSig must panic for the following (example) types:
 683  	// int
 684  	makeSig(Typ[Int], false)
 685  
 686  	// P where P's type set doesn't have any specific types
 687  	{
 688  		P := NewTypeName(nopos, nil, "P", nil) // [P any]
 689  		makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Universe.Lookup("any").Type()})), false)
 690  	}
 691  
 692  	// P where P's type set doesn't have any slice or string types
 693  	{
 694  		P := NewTypeName(nopos, nil, "P", nil) // [P any]
 695  		makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[Int]})), false)
 696  	}
 697  }
 698  
 699  func TestIssue51093(t *testing.T) {
 700  	// Each test stands for a conversion of the form P(val)
 701  	// where P is a type parameter with typ as constraint.
 702  	// The test ensures that P(val) has the correct type P
 703  	// and is not a constant.
 704  	var tests = []struct {
 705  		typ string
 706  		val string
 707  	}{
 708  		{"bool", "false"},
 709  		{"int", "-1"},
 710  		{"uint", "1.0"},
 711  		{"rune", "'a'"},
 712  		{"float64", "3.5"},
 713  		{"complex64", "1.25"},
 714  		{"string", "\"foo\""},
 715  
 716  		// some more complex constraints
 717  		{"~byte", "1"},
 718  		{"~int | ~float64 | complex128", "1"},
 719  		{"~uint64 | ~rune", "'X'"},
 720  	}
 721  
 722  	for _, test := range tests {
 723  		src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val)
 724  		types := make(map[ast.Expr]TypeAndValue)
 725  		mustTypecheck(src, nil, &Info{Types: types})
 726  
 727  		var n int
 728  		for x, tv := range types {
 729  			if x, _ := x.(*ast.CallExpr); x != nil {
 730  				// there must be exactly one CallExpr which is the P(val) conversion
 731  				n++
 732  				tpar, _ := tv.Type.(*TypeParam)
 733  				if tpar == nil {
 734  					t.Fatalf("%s: got type %s, want type parameter", ExprString(x), tv.Type)
 735  				}
 736  				if name := tpar.Obj().Name(); name != "P" {
 737  					t.Fatalf("%s: got type parameter name %s, want P", ExprString(x), name)
 738  				}
 739  				// P(val) must not be constant
 740  				if tv.Value != nil {
 741  					t.Errorf("%s: got constant value %s (%s), want no constant", ExprString(x), tv.Value, tv.Value.String())
 742  				}
 743  			}
 744  		}
 745  
 746  		if n != 1 {
 747  			t.Fatalf("%s: got %d CallExpr nodes; want 1", src, 1)
 748  		}
 749  	}
 750  }
 751  
 752  func TestIssue54258(t *testing.T) {
 753  
 754  	tests := []struct{ main, b, want string }{
 755  		{ //---------------------------------------------------------------
 756  			`package main
 757  import "b"
 758  type I0 interface {
 759  	M0(w struct{ f string })
 760  }
 761  var _ I0 = b.S{}
 762  `,
 763  			`package b
 764  type S struct{}
 765  func (S) M0(struct{ f string }) {}
 766  `,
 767  			`6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I0 value in variable declaration: b[.]S does not implement I0 [(]wrong type for method M0[)]
 768  .*have M0[(]struct{f string /[*] package b [*]/ }[)]
 769  .*want M0[(]struct{f string /[*] package main [*]/ }[)]`},
 770  
 771  		{ //---------------------------------------------------------------
 772  			`package main
 773  import "b"
 774  type I1 interface {
 775  	M1(struct{ string })
 776  }
 777  var _ I1 = b.S{}
 778  `,
 779  			`package b
 780  type S struct{}
 781  func (S) M1(struct{ string }) {}
 782  `,
 783  			`6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I1 value in variable declaration: b[.]S does not implement I1 [(]wrong type for method M1[)]
 784  .*have M1[(]struct{string /[*] package b [*]/ }[)]
 785  .*want M1[(]struct{string /[*] package main [*]/ }[)]`},
 786  
 787  		{ //---------------------------------------------------------------
 788  			`package main
 789  import "b"
 790  type I2 interface {
 791  	M2(y struct{ f struct{ f string } })
 792  }
 793  var _ I2 = b.S{}
 794  `,
 795  			`package b
 796  type S struct{}
 797  func (S) M2(struct{ f struct{ f string } }) {}
 798  `,
 799  			`6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I2 value in variable declaration: b[.]S does not implement I2 [(]wrong type for method M2[)]
 800  .*have M2[(]struct{f struct{f string} /[*] package b [*]/ }[)]
 801  .*want M2[(]struct{f struct{f string} /[*] package main [*]/ }[)]`},
 802  
 803  		{ //---------------------------------------------------------------
 804  			`package main
 805  import "b"
 806  type I3 interface {
 807  	M3(z struct{ F struct{ f string } })
 808  }
 809  var _ I3 = b.S{}
 810  `,
 811  			`package b
 812  type S struct{}
 813  func (S) M3(struct{ F struct{ f string } }) {}
 814  `,
 815  			`6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I3 value in variable declaration: b[.]S does not implement I3 [(]wrong type for method M3[)]
 816  .*have M3[(]struct{F struct{f string /[*] package b [*]/ }}[)]
 817  .*want M3[(]struct{F struct{f string /[*] package main [*]/ }}[)]`},
 818  
 819  		{ //---------------------------------------------------------------
 820  			`package main
 821  import "b"
 822  type I4 interface {
 823  	M4(_ struct { *string })
 824  }
 825  var _ I4 = b.S{}
 826  `,
 827  			`package b
 828  type S struct{}
 829  func (S) M4(struct { *string }) {}
 830  `,
 831  			`6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I4 value in variable declaration: b[.]S does not implement I4 [(]wrong type for method M4[)]
 832  .*have M4[(]struct{[*]string /[*] package b [*]/ }[)]
 833  .*want M4[(]struct{[*]string /[*] package main [*]/ }[)]`},
 834  
 835  		{ //---------------------------------------------------------------
 836  			`package main
 837  import "b"
 838  type t struct{ A int }
 839  type I5 interface {
 840  	M5(_ struct {b.S;t})
 841  }
 842  var _ I5 = b.S{}
 843  `,
 844  			`package b
 845  type S struct{}
 846  type t struct{ A int }
 847  func (S) M5(struct {S;t}) {}
 848  `,
 849  			`7:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I5 value in variable declaration: b[.]S does not implement I5 [(]wrong type for method M5[)]
 850  .*have M5[(]struct{b[.]S; b[.]t}[)]
 851  .*want M5[(]struct{b[.]S; t}[)]`},
 852  	}
 853  
 854  	fset := token.NewFileSet()
 855  	test := func(main, b, want string) {
 856  		re := regexp.MustCompile(want)
 857  		bpkg := mustTypecheck(b, nil, nil)
 858  		mast := mustParse(fset, main)
 859  		conf := Config{Importer: importHelper{pkg: bpkg}}
 860  		_, err := conf.Check(mast.Name.Name, fset, []*ast.File{mast}, nil)
 861  		if err == nil {
 862  			t.Error("Expected failure, but it did not")
 863  		} else if got := err.Error(); !re.MatchString(got) {
 864  			t.Errorf("Wanted match for\n\t%s\n but got\n\t%s", want, got)
 865  		} else if testing.Verbose() {
 866  			t.Logf("Saw expected\n\t%s", err.Error())
 867  		}
 868  	}
 869  	for _, t := range tests {
 870  		test(t.main, t.b, t.want)
 871  	}
 872  }
 873  
 874  func TestIssue59944(t *testing.T) {
 875  	testenv.MustHaveCGO(t)
 876  
 877  	// Methods declared on aliases of cgo types are not permitted.
 878  	const src = `// -gotypesalias=1
 879  
 880  package p
 881  
 882  /*
 883  struct layout {};
 884  */
 885  import "C"
 886  
 887  type Layout = C.struct_layout
 888  
 889  func (*Layout /* ERROR "cannot define new methods on non-local type Layout" */) Binding() {}
 890  `
 891  
 892  	// code generated by cmd/cgo for the above source.
 893  	const cgoTypes = `
 894  // Code generated by cmd/cgo; DO NOT EDIT.
 895  
 896  package p
 897  
 898  import "unsafe"
 899  
 900  import "syscall"
 901  
 902  import _cgopackage "runtime/cgo"
 903  
 904  type _ _cgopackage.Incomplete
 905  var _ syscall.Errno
 906  func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }
 907  
 908  //go:linkname _Cgo_always_false runtime.cgoAlwaysFalse
 909  var _Cgo_always_false bool
 910  //go:linkname _Cgo_use runtime.cgoUse
 911  func _Cgo_use(interface{})
 912  //go:linkname _Cgo_keepalive runtime.cgoKeepAlive
 913  //go:noescape
 914  func _Cgo_keepalive(interface{})
 915  //go:linkname _Cgo_no_callback runtime.cgoNoCallback
 916  func _Cgo_no_callback(bool)
 917  type _Ctype_struct_layout struct {
 918  }
 919  
 920  type _Ctype_void [0]byte
 921  
 922  //go:linkname _cgo_runtime_cgocall runtime.cgocall
 923  func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
 924  
 925  //go:linkname _cgoCheckPointer runtime.cgoCheckPointer
 926  //go:noescape
 927  func _cgoCheckPointer(interface{}, interface{})
 928  
 929  //go:linkname _cgoCheckResult runtime.cgoCheckResult
 930  //go:noescape
 931  func _cgoCheckResult(interface{})
 932  `
 933  	testFiles(t, []string{"p.go", "_cgo_gotypes.go"}, [][]byte{[]byte(src), []byte(cgoTypes)}, false, func(cfg *Config) {
 934  		*boolFieldAddr(cfg, "go115UsesCgo") = true
 935  	})
 936  }
 937  
 938  func TestIssue61931(t *testing.T) {
 939  	const src = `
 940  package p
 941  
 942  func A(func(any), ...any) {}
 943  func B[T any](T)          {}
 944  
 945  func _() {
 946  	A(B, nil // syntax error: missing ',' before newline in argument list
 947  }
 948  `
 949  	fset := token.NewFileSet()
 950  	f, err := parser.ParseFile(fset, pkgName(src), src, 0)
 951  	if err == nil {
 952  		t.Fatal("expected syntax error")
 953  	}
 954  
 955  	var conf Config
 956  	conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // must not panic
 957  }
 958  
 959  func TestIssue61938(t *testing.T) {
 960  	const src = `
 961  package p
 962  
 963  func f[T any]() {}
 964  func _()        { f() }
 965  `
 966  	// no error handler provided (this issue)
 967  	var conf Config
 968  	typecheck(src, &conf, nil) // must not panic
 969  
 970  	// with error handler (sanity check)
 971  	conf.Error = func(error) {}
 972  	typecheck(src, &conf, nil) // must not panic
 973  }
 974  
 975  func TestIssue63260(t *testing.T) {
 976  	const src = `
 977  package p
 978  
 979  func _() {
 980          use(f[*string])
 981  }
 982  
 983  func use(func()) {}
 984  
 985  func f[I *T, T any]() {
 986          var v T
 987          _ = v
 988  }`
 989  
 990  	info := Info{
 991  		Defs: make(map[*ast.Ident]Object),
 992  	}
 993  	pkg := mustTypecheck(src, nil, &info)
 994  
 995  	// get type parameter T in signature of f
 996  	T := pkg.Scope().Lookup("f").Type().(*Signature).TypeParams().At(1)
 997  	if T.Obj().Name() != "T" {
 998  		t.Fatalf("got type parameter %s, want T", T)
 999  	}
1000  
1001  	// get type of variable v in body of f
1002  	var v Object
1003  	for name, obj := range info.Defs {
1004  		if name.Name == "v" {
1005  			v = obj
1006  			break
1007  		}
1008  	}
1009  	if v == nil {
1010  		t.Fatal("variable v not found")
1011  	}
1012  
1013  	// type of v and T must be pointer-identical
1014  	if v.Type() != T {
1015  		t.Fatalf("types of v and T are not pointer-identical: %p != %p", v.Type().(*TypeParam), T)
1016  	}
1017  }
1018  
1019  func TestIssue44410(t *testing.T) {
1020  	const src = `
1021  package p
1022  
1023  type A = []int
1024  type S struct{ A }
1025  `
1026  
1027  	t.Setenv("GODEBUG", "gotypesalias=1")
1028  	pkg := mustTypecheck(src, nil, nil)
1029  
1030  	S := pkg.Scope().Lookup("S")
1031  	if S == nil {
1032  		t.Fatal("object S not found")
1033  	}
1034  
1035  	got := S.String()
1036  	const want = "type p.S struct{p.A}"
1037  	if got != want {
1038  		t.Fatalf("got %q; want %q", got, want)
1039  	}
1040  }
1041  
1042  func TestIssue59831(t *testing.T) {
1043  	// Package a exports a type S with an unexported method m;
1044  	// the tests check the error messages when m is not found.
1045  	const asrc = `package a; type S struct{}; func (S) m() {}`
1046  	apkg := mustTypecheck(asrc, nil, nil)
1047  
1048  	// Package b exports a type S with an exported method m;
1049  	// the tests check the error messages when M is not found.
1050  	const bsrc = `package b; type S struct{}; func (S) M() {}`
1051  	bpkg := mustTypecheck(bsrc, nil, nil)
1052  
1053  	tests := []struct {
1054  		imported *Package
1055  		src, err string
1056  	}{
1057  		// tests importing a (or nothing)
1058  		{apkg, `package a1; import "a"; var _ interface { M() } = a.S{}`,
1059  			"a.S does not implement interface{M()} (missing method M) have m() want M()"},
1060  
1061  		{apkg, `package a2; import "a"; var _ interface { m() } = a.S{}`,
1062  			"a.S does not implement interface{m()} (unexported method m)"}, // test for issue
1063  
1064  		{nil, `package a3; type S struct{}; func (S) m(); var _ interface { M() } = S{}`,
1065  			"S does not implement interface{M()} (missing method M) have m() want M()"},
1066  
1067  		{nil, `package a4; type S struct{}; func (S) m(); var _ interface { m() } = S{}`,
1068  			""}, // no error expected
1069  
1070  		{nil, `package a5; type S struct{}; func (S) m(); var _ interface { n() } = S{}`,
1071  			"S does not implement interface{n()} (missing method n)"},
1072  
1073  		// tests importing b (or nothing)
1074  		{bpkg, `package b1; import "b"; var _ interface { m() } = b.S{}`,
1075  			"b.S does not implement interface{m()} (missing method m) have M() want m()"},
1076  
1077  		{bpkg, `package b2; import "b"; var _ interface { M() } = b.S{}`,
1078  			""}, // no error expected
1079  
1080  		{nil, `package b3; type S struct{}; func (S) M(); var _ interface { M() } = S{}`,
1081  			""}, // no error expected
1082  
1083  		{nil, `package b4; type S struct{}; func (S) M(); var _ interface { m() } = S{}`,
1084  			"S does not implement interface{m()} (missing method m) have M() want m()"},
1085  
1086  		{nil, `package b5; type S struct{}; func (S) M(); var _ interface { n() } = S{}`,
1087  			"S does not implement interface{n()} (missing method n)"},
1088  	}
1089  
1090  	for _, test := range tests {
1091  		// typecheck test source
1092  		conf := Config{Importer: importHelper{pkg: test.imported}}
1093  		pkg, err := typecheck(test.src, &conf, nil)
1094  		if err == nil {
1095  			if test.err != "" {
1096  				t.Errorf("package %s: got no error, want %q", pkg.Name(), test.err)
1097  			}
1098  			continue
1099  		}
1100  		if test.err == "" {
1101  			t.Errorf("package %s: got %q, want not error", pkg.Name(), err.Error())
1102  		}
1103  
1104  		// flatten reported error message
1105  		errmsg := strings.ReplaceAll(err.Error(), "\n", " ")
1106  		errmsg = strings.ReplaceAll(errmsg, "\t", "")
1107  
1108  		// verify error message
1109  		if !strings.Contains(errmsg, test.err) {
1110  			t.Errorf("package %s: got %q, want %q", pkg.Name(), errmsg, test.err)
1111  		}
1112  	}
1113  }
1114  
1115  func TestIssue64759(t *testing.T) {
1116  	const src = `
1117  //go:build go1.18
1118  package p
1119  
1120  func f[S ~[]E, E any](S) {}
1121  
1122  func _() {
1123  	f([]string{})
1124  }
1125  `
1126  	// Per the go:build directive, the source must typecheck
1127  	// even though the (module) Go version is set to go1.17.
1128  	conf := Config{GoVersion: "go1.17"}
1129  	mustTypecheck(src, &conf, nil)
1130  }
1131  
1132  func TestIssue68334(t *testing.T) {
1133  	const src = `
1134  package p
1135  
1136  func f(x int) {
1137  	for i, j := range x {
1138  		_, _ = i, j
1139  	}
1140  	var a, b int
1141  	for a, b = range x {
1142  		_, _ = a, b
1143  	}
1144  }
1145  `
1146  
1147  	got := ""
1148  	conf := Config{
1149  		GoVersion: "go1.21",                                      // #68334 requires GoVersion <= 1.21
1150  		Error:     func(err error) { got += err.Error() + "\n" }, // #68334 requires Error != nil
1151  	}
1152  	typecheck(src, &conf, nil) // do not crash
1153  
1154  	want := "p:5:20: cannot range over x (variable of type int): requires go1.22 or later\n" +
1155  		"p:9:19: cannot range over x (variable of type int): requires go1.22 or later\n"
1156  	if got != want {
1157  		t.Errorf("got: %s want: %s", got, want)
1158  	}
1159  }
1160  
1161  func TestIssue68877(t *testing.T) {
1162  	const src = `
1163  package p
1164  
1165  type (
1166  	S struct{}
1167  	A = S
1168  	T A
1169  )`
1170  
1171  	t.Setenv("GODEBUG", "gotypesalias=1")
1172  	pkg := mustTypecheck(src, nil, nil)
1173  	T := pkg.Scope().Lookup("T").(*TypeName)
1174  	got := T.String() // this must not panic (was issue)
1175  	const want = "type p.T struct{}"
1176  	if got != want {
1177  		t.Errorf("got %s, want %s", got, want)
1178  	}
1179  }
1180  
1181  func TestIssue69092(t *testing.T) {
1182  	const src = `
1183  package p
1184  
1185  var _ = T{{x}}
1186  `
1187  
1188  	fset := token.NewFileSet()
1189  	file := mustParse(fset, src)
1190  	conf := Config{Error: func(err error) {}} // ignore errors
1191  	info := Info{Types: make(map[ast.Expr]TypeAndValue)}
1192  	conf.Check("p", fset, []*ast.File{file}, &info)
1193  
1194  	// look for {x} expression
1195  	outer := file.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0].(*ast.CompositeLit) // T{{x}}
1196  	inner := outer.Elts[0]                                                                        // {x}
1197  
1198  	// type of {x} must have been recorded
1199  	tv, ok := info.Types[inner]
1200  	if !ok {
1201  		t.Fatal("no type found for {x}")
1202  	}
1203  	if tv.Type != Typ[Invalid] {
1204  		t.Fatalf("unexpected type for {x}: %s", tv.Type)
1205  	}
1206  }
1207