. "cmd/compile/internal/types2"
)
-// brokenPkg is a source prefix for packages that are not expected to parse
-// or type-check cleanly. They are always parsed assuming that they contain
-// generic code.
-const brokenPkg = "package broken_"
-
-func parseSrc(path, src string) (*syntax.File, error) {
+func parse(path, src string) (*syntax.File, error) {
errh := func(error) {} // dummy error handler so that parsing continues in presence of errors
return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, 0)
}
-func pkgFor(path, source string, info *Info) (*Package, error) {
- f, err := parseSrc(path, source)
+func mustParse(path, src string) *syntax.File {
+ f, err := parse(path, src)
if err != nil {
- return nil, err
+ panic(err) // so we don't need to pass *testing.T
}
- conf := Config{Importer: defaultImporter()}
- return conf.Check(f.PkgName.Value, []*syntax.File{f}, info)
-}
-
-func mustTypecheck(t testing.TB, path, source string, info *Info) string {
- pkg, err := pkgFor(path, source, info)
- if err != nil {
- name := path
- if pkg != nil {
- name = "package " + pkg.Name()
- }
- t.Fatalf("%s: didn't type-check (%s)", name, err)
- }
- return pkg.Name()
+ return f
}
-func mayTypecheck(t *testing.T, path, source string, info *Info) (string, error) {
- f, err := parseSrc(path, source)
+func typecheck(path, src string, info *Info) (*Package, error) {
+ f, err := parse(path, src)
if f == nil { // ignore errors unless f is nil
- t.Fatalf("%s: unable to parse: %s", path, err)
+ return nil, err
}
conf := Config{
- Error: func(err error) {},
+ Error: func(err error) {}, // collect all errors
Importer: defaultImporter(),
}
- pkg, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, info)
- return pkg.Name(), err
+ return conf.Check(f.PkgName.Value, []*syntax.File{f}, info)
+}
+
+func mustTypecheck(path, src string, info *Info) string {
+ pkg, err := typecheck(path, src, info)
+ if err != nil {
+ panic(err) // so we don't need to pass *testing.T
+ }
+ return pkg.Name()
}
func TestValuesInfo(t *testing.T) {
info := Info{
Types: make(map[syntax.Expr]TypeAndValue),
}
- name := mustTypecheck(t, "ValuesInfo", test.src, &info)
+ name := mustTypecheck("ValuesInfo", test.src, &info)
// look for expression
var expr syntax.Expr
}
func TestTypesInfo(t *testing.T) {
+ // Test sources that are not expected to typecheck must start with the broken prefix.
+ const brokenPkg = "package broken_"
+
var tests = []struct {
src string
expr string // expression
info := Info{Types: make(map[syntax.Expr]TypeAndValue)}
var name string
if strings.HasPrefix(test.src, brokenPkg) {
- var err error
- name, err = mayTypecheck(t, "TypesInfo", test.src, &info)
+ pkg, err := typecheck("TypesInfo", test.src, &info)
if err == nil {
- t.Errorf("package %s: expected to fail but passed", name)
+ t.Errorf("package %s: expected to fail but passed", pkg.Name())
continue
}
+ if pkg != nil {
+ name = pkg.Name()
+ }
} else {
- name = mustTypecheck(t, "TypesInfo", test.src, &info)
+ name = mustTypecheck("TypesInfo", test.src, &info)
}
// look for expression type
instMap := make(map[*syntax.Name]Instance)
useMap := make(map[*syntax.Name]Object)
makePkg := func(src string) *Package {
- f, err := parseSrc("p.go", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("p.go", src)
pkg, err := conf.Check("", []*syntax.File{f}, &Info{Instances: instMap, Uses: useMap})
if err != nil {
t.Fatal(err)
info := Info{
Defs: make(map[*syntax.Name]Object),
}
- name := mustTypecheck(t, "DefsInfo", test.src, &info)
+ name := mustTypecheck("DefsInfo", test.src, &info)
// find object
var def Object
info := Info{
Uses: make(map[*syntax.Name]Object),
}
- name := mustTypecheck(t, "UsesInfo", test.src, &info)
+ name := mustTypecheck("UsesInfo", test.src, &info)
// find object
var use Object
func (r *N[C]) n() { }
`
- f, err := parseSrc("p.go", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("p.go", src)
info := Info{
Defs: make(map[*syntax.Name]Object),
Uses: make(map[*syntax.Name]Object),
info := Info{
Implicits: make(map[syntax.Node]Object),
}
- name := mustTypecheck(t, "ImplicitsInfo", test.src, &info)
+ name := mustTypecheck("ImplicitsInfo", test.src, &info)
// the test cases expect at most one Implicits entry
if len(info.Implicits) > 1 {
for _, test := range tests {
info := Info{Types: make(map[syntax.Expr]TypeAndValue)}
- name := mustTypecheck(t, "PredicatesInfo", test.src, &info)
+ name := mustTypecheck("PredicatesInfo", test.src, &info)
// look for expression predicates
got := "<missing>"
for _, test := range tests {
info := Info{Scopes: make(map[syntax.Node]*Scope)}
- name := mustTypecheck(t, "ScopesInfo", test.src, &info)
+ name := mustTypecheck("ScopesInfo", test.src, &info)
// number of scopes must match
if len(info.Scopes) != len(test.scopes) {
for _, test := range tests {
info := Info{}
- name := mustTypecheck(t, "InitOrderInfo", test.src, &info)
+ name := mustTypecheck("InitOrderInfo", test.src, &info)
// number of initializers must match
if len(info.InitOrder) != len(test.inits) {
}
func TestMultiFileInitOrder(t *testing.T) {
- mustParse := func(src string) *syntax.File {
- f, err := parseSrc("main", src)
- if err != nil {
- t.Fatal(err)
- }
- return f
- }
-
- fileA := mustParse(`package main; var a = 1`)
- fileB := mustParse(`package main; var b = 2`)
+ fileA := mustParse("", `package main; var a = 1`)
+ fileB := mustParse("", `package main; var b = 2`)
// The initialization order must not depend on the parse
// order of the files, only on the presentation order to
for i, src := range sources {
filename := fmt.Sprintf("sources%d", i)
- f, err := parseSrc(filename, src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(filename, src)
if err := check.Files([]*syntax.File{f}); err != nil {
t.Error(err)
}
imports := make(testImporter)
conf := Config{Importer: imports}
makePkg := func(path, src string) {
- f, err := parseSrc(path+".go", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(path+".go", src)
pkg, err := conf.Check(path, []*syntax.File{f}, &Info{Selections: selections})
if err != nil {
t.Fatal(err)
Importer: imports,
}
makePkg := func(path, src string) {
- f, err := parseSrc(path, src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(path, src)
pkg, _ := conf.Check(path, []*syntax.File{f}, nil) // errors logged via conf.Error
imports[path] = pkg
}
}
for _, test := range tests {
- pkg, err := pkgFor("test", "package p;"+test.src, nil)
+ pkg, err := typecheck("test", "package p;"+test.src, nil)
if err != nil {
t.Errorf("%s: incorrect test case: %s", test.src, err)
continue
type Instance = *Tree[int]
`
- f, err := parseSrc("foo.go", src)
- if err != nil {
- panic(err)
- }
+ f := mustParse("foo.go", src)
pkg := NewPackage("pkg", f.PkgName.Value)
if err := NewChecker(nil, pkg, nil).Files([]*syntax.File{f}); err != nil {
panic(err)
conf := Config{Importer: imports}
var info Info
makePkg := func(path, src string) {
- f, err := parseSrc(path, src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(path, src)
+ var err error
imports[path], err = conf.Check(path, []*syntax.File{f}, &info)
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
- pkg, err := pkgFor("test", "package p;"+test.src, nil)
+ pkg, err := typecheck("test", "package p;"+test.src, nil)
if err != nil {
t.Errorf("%s: incorrect test case: %s", test.src, err)
continue
func TestIssue15305(t *testing.T) {
const src = "package p; func f() int16; var _ = f(undef)"
- f, err := parseSrc("issue15305.go", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("issue15305.go", src)
conf := Config{
Error: func(err error) {}, // allow errors
}
{`struct{}{}`, `struct{}`},
{`struct{x, y int; z complex128}{}`, `struct{x int; y int; z complex128}`},
} {
- f, err := parseSrc(test.lit, "package p; var _ = "+test.lit)
- if err != nil {
- t.Fatalf("%s: %v", test.lit, err)
- }
-
- info := &Info{
- Types: make(map[syntax.Expr]TypeAndValue),
- }
- if _, err = new(Config).Check("p", []*syntax.File{f}, info); err != nil {
+ f := mustParse(test.lit, "package p; var _ = "+test.lit)
+ types := make(map[syntax.Expr]TypeAndValue)
+ if _, err := new(Config).Check("p", []*syntax.File{f}, &Info{Types: types}); err != nil {
t.Fatalf("%s: %v", test.lit, err)
}
cmptype := func(x syntax.Expr, want string) {
- tv, ok := info.Types[x]
+ tv, ok := types[x]
if !ok {
t.Errorf("%s: no Types entry found", test.lit)
return
func f(x int) { y := x; print(y) }
`
- f, err := parseSrc("src", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("src", src)
info := &Info{
Defs: make(map[*syntax.Name]Object),
}
- if _, err = new(Config).Check("p", []*syntax.File{f}, info); err != nil {
+ if _, err := new(Config).Check("p", []*syntax.File{f}, info); err != nil {
t.Fatal(err)
}
var v T = c
func f(x T) T { return foo.F(x) }
`
- f, err := parseSrc("src", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("src", src)
files := []*syntax.File{f}
// type-check using all possible importers
func TestInstantiate(t *testing.T) {
// eventually we like more tests but this is a start
const src = "package p; type T[P any] *T[P]"
- pkg, err := pkgFor(".", src, nil)
+ pkg, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
src := "package p; " + test.src
- pkg, err := pkgFor(".", src, nil)
+ pkg, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
imports := make(testImporter)
conf := Config{Importer: imports}
makePkg := func(src string) {
- f, err := parseSrc("", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("", src)
name := f.PkgName.Value
pkg, err := conf.Check(name, []*syntax.File{f}, nil)
if err != nil {
info := &Info{
Defs: make(map[*syntax.Name]Object),
}
- f, err := parseSrc("p.go", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("p.go", src)
conf := Config{}
pkg, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, info)
if err != nil {
type Bad Bad // invalid type
`
- f, err := parseSrc("p.go", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("p.go", src)
conf := Config{Error: func(error) {}}
pkg, _ := conf.Check(f.PkgName.Value, []*syntax.File{f}, nil)
func (V4) M()
`
- pkg, err := pkgFor("p.go", src, nil)
+ pkg, err := typecheck("p.go", src, nil)
if err != nil {
t.Fatal(err)
}
func Unused() { {}; {{ var x int; _ = x }} } // make sure empty block scopes get printed
`},
} {
- f, err := parseSrc(file.name, file.input)
- if err != nil {
- log.Fatal(err)
- }
- files = append(files, f)
+ files = append(files, mustParse(file.name, file.input))
}
// Type-check a package consisting of these files.
}
return fib(x-1) - fib(x-2)
}`
- f, err := parseSrc("fib.go", input)
- if err != nil {
- log.Fatal(err)
- }
+ f := mustParse("fib.go", input)
// Type-check the package.
// We create an empty map for each kind of input
}
for _, test := range tests {
- pkg, err := pkgFor(".", test.src, nil)
+ pkg, err := typecheck(".", test.src, nil)
if err != nil {
t.Fatal(err)
}
func TestInstantiateNonEquality(t *testing.T) {
const src = "package p; type T[P any] int"
- pkg1, err := pkgFor(".", src, nil)
+ pkg1, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
- pkg2, err := pkgFor(".", src, nil)
+ pkg2, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
src := prefix + test.decl
- pkg, err := pkgFor(".", src, nil)
+ pkg, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
var _ T[int]
`
- pkg, err := pkgFor(".", src, nil)
+ pkg, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
. "cmd/compile/internal/types2"
)
-func mustParse(t *testing.T, src string) *syntax.File {
- f, err := parseSrc("", src)
- if err != nil {
- t.Fatal(err)
- }
- return f
-}
func TestIssue5770(t *testing.T) {
- f := mustParse(t, `package p; type S struct{T}`)
+ f := mustParse("", `package p; type S struct{T}`)
var conf Config
_, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, nil) // do not crash
const want = "undefined: T"
_ = (interface{})(nil)
)`
types := make(map[syntax.Expr]TypeAndValue)
- mustTypecheck(t, "p", src, &Info{Types: types})
+ mustTypecheck("p", src, &Info{Types: types})
for x, tv := range types {
var want Type
}
`
types := make(map[syntax.Expr]TypeAndValue)
- mustTypecheck(t, "p", src, &Info{Types: types})
+ mustTypecheck("p", src, &Info{Types: types})
want := Typ[Int]
n := 0
func (T) m() (res bool) { return }
type T struct{} // receiver type after method declaration
`
- f := mustParse(t, src)
+ f := mustParse("", src)
var conf Config
defs := make(map[*syntax.Name]Object)
_, _, _ = x, y, z // uses x, y, z
}
`
- f := mustParse(t, src)
+ f := mustParse("", src)
const want = `L3 defs func p._()
L4 defs const w untyped int
}
`
f := func(test, src string) {
- f := mustParse(t, src)
+ f := mustParse("", src)
conf := Config{Importer: defaultImporter()}
info := Info{Uses: make(map[*syntax.Name]Object)}
_, err := conf.Check("main", []*syntax.File{f}, &info)
}
func TestIssue22525(t *testing.T) {
- f := mustParse(t, `package p; func f() { var a, b, c, d, e int }`)
+ f := mustParse("", `package p; func f() { var a, b, c, d, e int }`)
got := "\n"
conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
`struct { *I }`,
`struct { a int; b Missing; *Missing }`,
} {
- f := mustParse(t, prefix+src)
+ f := mustParse("", prefix+src)
conf := Config{Importer: defaultImporter(), Error: func(err error) {}}
info := &Info{Types: make(map[syntax.Expr]TypeAndValue)}
// compute original file ASTs
var orig [len(sources)]*syntax.File
for i, src := range sources {
- orig[i] = mustParse(t, src)
+ orig[i] = mustParse("", src)
}
// run the test for all order permutations of the incoming files
}
func TestIssue29029(t *testing.T) {
- f1 := mustParse(t, `package p; type A interface { M() }`)
- f2 := mustParse(t, `package p; var B interface { A }`)
+ f1 := mustParse("", `package p; type A interface { M() }`)
+ f2 := mustParse("", `package p; var B interface { A }`)
// printInfo prints the *Func definitions recorded in info, one *Func per line.
printInfo := func(info *Info) string {
const asrc = `package a; type I interface{ M() }; type T struct { F interface { I } }`
const bsrc = `package b; import "a"; type T struct { F interface { a.I } }; var _ = a.T(T{})`
- a, err := pkgFor("a", asrc, nil)
+ a, err := typecheck("a", asrc, nil)
if err != nil {
t.Fatalf("package %s failed to typecheck: %v", a.Name(), err)
}
- bast := mustParse(t, bsrc)
+ bast := mustParse("", bsrc)
conf := Config{Importer: importHelper{pkg: a}}
b, err := conf.Check(bast.PkgName.Value, []*syntax.File{bast}, nil)
if err != nil {
var pkg *Package
for _, src := range sources {
- f := mustParse(t, src)
+ f := mustParse("", src)
conf := Config{Importer: importHelper{pkg: pkg}}
res, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, nil)
if err != nil {
csrc = `package c; import ("a"; "html/template"); func _() { a.G(template.Template{}) }`
)
- a, err := pkgFor("a", asrc, nil)
+ a, err := typecheck("a", asrc, nil)
if err != nil {
t.Fatalf("package a failed to typecheck: %v", err)
}
// Packages should be fully qualified when there is ambiguity within the
// error string itself.
- bast := mustParse(t, bsrc)
+ bast := mustParse("", bsrc)
_, err = conf.Check(bast.PkgName.Value, []*syntax.File{bast}, nil)
if err == nil {
t.Fatal("package b had no errors")
}
// ...and also when there is any ambiguity in reachable packages.
- cast := mustParse(t, csrc)
+ cast := mustParse("", csrc)
_, err = conf.Check(cast.PkgName.Value, []*syntax.File{cast}, nil)
if err == nil {
t.Fatal("package c had no errors")
for _, test := range tests {
src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val)
types := make(map[syntax.Expr]TypeAndValue)
- mustTypecheck(t, "p", src, &Info{Types: types})
+ mustTypecheck("p", src, &Info{Types: types})
var n int
for x, tv := range types {
type Inst = G[int]
`
- pkg, err := pkgFor("p", src, nil)
+ pkg, err := typecheck("p", src, nil)
if err != nil {
b.Fatal(err)
}
type Inst = *Tree[int]
`
- f, err := parseSrc("foo.go", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("foo.go", src)
pkg := NewPackage("p", f.PkgName.Value)
if err := NewChecker(nil, pkg, nil).Files([]*syntax.File{f}); err != nil {
t.Fatal(err)
const src = `package p; type I interface { error }`
// type-check src
- f, err := parseSrc("", src)
- if err != nil {
- t.Fatalf("parse failed: %s", err)
- }
+ f := mustParse("", src)
var conf Config
pkg, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, nil)
if err != nil {
for _, test := range testObjects {
src := "package p; " + test.src
- pkg, err := makePkg(src)
+ pkg, err := typecheck(filename, src, nil)
if err != nil {
t.Errorf("%s: %s", src, err)
continue
// parse package files
var files []*syntax.File
for i, src := range sources {
- f, err := parseSrc(fmt.Sprintf("sources[%d]", i), src)
- if err != nil {
- t.Fatal(err)
- }
- files = append(files, f)
+ files = append(files, mustParse(fmt.Sprintf("sources[%d]", i), src))
}
// resolve and type-check package AST
}
func findStructTypeConfig(t *testing.T, src string, conf *types2.Config) *types2.Struct {
- f, err := parseSrc("x.go", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("x.go", src)
info := types2.Info{Types: make(map[syntax.Expr]types2.TypeAndValue)}
- _, err = conf.Check("x", []*syntax.File{f}, &info)
+ _, err := conf.Check("x", []*syntax.File{f}, &info)
if err != nil {
t.Fatal(err)
}
const _ = unsafe.Offsetof(struct{ x int64 }{}.x)
`
- f, err := parseSrc("x.go", src)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse("x.go", src)
info := types2.Info{Types: make(map[syntax.Expr]types2.TypeAndValue)}
conf := types2.Config{
Importer: defaultImporter(),
Sizes: &types2.StdSizes{WordSize: 8, MaxAlign: 8},
}
- _, err = conf.Check("x", []*syntax.File{f}, &info)
+ _, err := conf.Check("x", []*syntax.File{f}, &info)
if err != nil {
t.Fatal(err)
}
pkgCount := 0
duration := walkPkgDirs(filepath.Join(testenv.GOROOT(t), "src"), func(dir string, filenames []string) {
- typecheck(t, dir, filenames)
+ typecheckFiles(t, dir, filenames)
pkgCount++
}, t.Error)
"crypto/internal/edwards25519/field/_asm": true,
}
-// typecheck typechecks the given package files.
-func typecheck(t *testing.T, path string, filenames []string) {
+// typecheckFiles typechecks the given package files.
+func typecheckFiles(t *testing.T, path string, filenames []string) {
// parse package files
var files []*syntax.File
for _, filename := range filenames {
"internal/testenv"
"testing"
- "cmd/compile/internal/syntax"
. "cmd/compile/internal/types2"
)
const filename = "<src>"
-func makePkg(src string) (*Package, error) {
- file, err := parseSrc(filename, src)
- if err != nil {
- return nil, err
- }
- // use the package name as package path
- conf := Config{Importer: defaultImporter()}
- return conf.Check(file.PkgName.Value, []*syntax.File{file}, nil)
-}
-
type testEntry struct {
src, str string
}
for _, test := range tests {
src := `package generic_p; import "io"; type _ io.Writer; type T ` + test.src
- pkg, err := makePkg(src)
+ pkg, err := typecheck(filename, src, nil)
if err != nil {
t.Errorf("%s: %s", src, err)
continue
}
func TestQualifiedTypeString(t *testing.T) {
- p, _ := pkgFor("p.go", "package p; type T int", nil)
- q, _ := pkgFor("q.go", "package q", nil)
+ p, _ := typecheck("p.go", "package p; type T int", nil)
+ q, _ := typecheck("q.go", "package q", nil)
pT := p.Scope().Lookup("T").Type()
for _, test := range []struct {
. "go/types"
)
-// pkgFor parses and type checks the package specified by path and source,
-// populating info if provided.
-func pkgFor(path, source string, info *Info) (*Package, error) {
- fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, path, source, 0)
- if err != nil {
- return nil, err
- }
- conf := Config{Importer: importer.Default()}
- return conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
+func parse(fset *token.FileSet, filename, src string) (*ast.File, error) {
+ return parser.ParseFile(fset, filename, src, 0)
}
-func mustTypecheck(t testing.TB, path, source string, info *Info) string {
- pkg, err := pkgFor(path, source, info)
+func mustParse(fset *token.FileSet, filename, src string) *ast.File {
+ f, err := parse(fset, filename, src)
if err != nil {
- name := path
- if pkg != nil {
- name = "package " + pkg.Name()
- }
- t.Fatalf("%s: didn't type-check (%s)", name, err)
+ panic(err) // so we don't need to pass *testing.T
}
- return pkg.Name()
+ return f
}
-func mayTypecheck(t *testing.T, path, source string, info *Info) (string, error) {
+func typecheck(path, src string, info *Info) (*Package, error) {
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, path, source, 0)
+ f, err := parse(fset, path, src)
if f == nil { // ignore errors unless f is nil
- t.Fatalf("%s: unable to parse: %s", path, err)
+ return nil, err
}
conf := Config{
- Error: func(err error) {},
+ Error: func(err error) {}, // collect all errors
Importer: importer.Default(),
}
- pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
- return pkg.Name(), err
+ return conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
+}
+
+func mustTypecheck(path, src string, info *Info) string {
+ pkg, err := typecheck(path, src, info)
+ if err != nil {
+ panic(err) // so we don't need to pass *testing.T
+ }
+ return pkg.Name()
}
func TestValuesInfo(t *testing.T) {
info := Info{
Types: make(map[ast.Expr]TypeAndValue),
}
- name := mustTypecheck(t, "ValuesInfo", test.src, &info)
+ name := mustTypecheck("ValuesInfo", test.src, &info)
// look for expression
var expr ast.Expr
info := Info{Types: make(map[ast.Expr]TypeAndValue)}
var name string
if strings.HasPrefix(test.src, broken) {
- var err error
- name, err = mayTypecheck(t, "TypesInfo", test.src, &info)
+ pkg, err := typecheck("TypesInfo", test.src, &info)
if err == nil {
- t.Errorf("package %s: expected to fail but passed", name)
+ t.Errorf("package %s: expected to fail but passed", pkg.Name())
continue
}
+ if pkg != nil {
+ name = pkg.Name()
+ }
} else {
- name = mustTypecheck(t, "TypesInfo", test.src, &info)
+ name = mustTypecheck("TypesInfo", test.src, &info)
}
// look for expression type
instMap := make(map[*ast.Ident]Instance)
useMap := make(map[*ast.Ident]Object)
makePkg := func(src string) *Package {
- f, err := parser.ParseFile(fset, "p.go", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "p.go", src)
pkg, err := conf.Check("", fset, []*ast.File{f}, &Info{Instances: instMap, Uses: useMap})
if err != nil {
t.Fatal(err)
info := Info{
Defs: make(map[*ast.Ident]Object),
}
- name := mustTypecheck(t, "DefsInfo", test.src, &info)
+ name := mustTypecheck("DefsInfo", test.src, &info)
// find object
var def Object
info := Info{
Uses: make(map[*ast.Ident]Object),
}
- name := mustTypecheck(t, "UsesInfo", test.src, &info)
+ name := mustTypecheck("UsesInfo", test.src, &info)
// find object
var use Object
func (r *N[C]) n() { }
`
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "p.go", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "p.go", src)
info := Info{
Defs: make(map[*ast.Ident]Object),
Uses: make(map[*ast.Ident]Object),
info := Info{
Implicits: make(map[ast.Node]Object),
}
- name := mustTypecheck(t, "ImplicitsInfo", test.src, &info)
+ name := mustTypecheck("ImplicitsInfo", test.src, &info)
// the test cases expect at most one Implicits entry
if len(info.Implicits) > 1 {
for _, test := range tests {
info := Info{Types: make(map[ast.Expr]TypeAndValue)}
- name := mustTypecheck(t, "PredicatesInfo", test.src, &info)
+ name := mustTypecheck("PredicatesInfo", test.src, &info)
// look for expression predicates
got := "<missing>"
for _, test := range tests {
info := Info{Scopes: make(map[ast.Node]*Scope)}
- name := mustTypecheck(t, "ScopesInfo", test.src, &info)
+ name := mustTypecheck("ScopesInfo", test.src, &info)
// number of scopes must match
if len(info.Scopes) != len(test.scopes) {
for _, test := range tests {
info := Info{}
- name := mustTypecheck(t, "InitOrderInfo", test.src, &info)
+ name := mustTypecheck("InitOrderInfo", test.src, &info)
// number of initializers must match
if len(info.InitOrder) != len(test.inits) {
func TestMultiFileInitOrder(t *testing.T) {
fset := token.NewFileSet()
- mustParse := func(src string) *ast.File {
- f, err := parser.ParseFile(fset, "main", src, 0)
- if err != nil {
- t.Fatal(err)
- }
- return f
- }
-
- fileA := mustParse(`package main; var a = 1`)
- fileB := mustParse(`package main; var b = 2`)
+ fileA := mustParse(fset, "", `package main; var a = 1`)
+ fileB := mustParse(fset, "", `package main; var b = 2`)
// The initialization order must not depend on the parse
// order of the files, only on the presentation order to
for i, src := range sources {
filename := fmt.Sprintf("sources%d", i)
- f, err := parser.ParseFile(fset, filename, src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, filename, src)
if err := check.Files([]*ast.File{f}); err != nil {
t.Error(err)
}
imports := make(testImporter)
conf := Config{Importer: imports}
makePkg := func(path, src string) {
- f, err := parser.ParseFile(fset, path+".go", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, path+".go", src)
pkg, err := conf.Check(path, fset, []*ast.File{f}, &Info{Selections: selections})
if err != nil {
t.Fatal(err)
Importer: imports,
}
makePkg := func(path, src string) {
- f, err := parser.ParseFile(fset, path, src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, path, src)
pkg, _ := conf.Check(path, fset, []*ast.File{f}, nil) // errors logged via conf.Error
imports[path] = pkg
}
}
for _, test := range tests {
- pkg, err := pkgFor("test", "package p;"+test.src, nil)
+ pkg, err := typecheck("test", "package p;"+test.src, nil)
if err != nil {
t.Errorf("%s: incorrect test case: %s", test.src, err)
continue
`
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "foo.go", src, 0)
- if err != nil {
- panic(err)
- }
+ f := mustParse(fset, "foo.go", src)
pkg := NewPackage("pkg", f.Name.Name)
if err := NewChecker(nil, fset, pkg, nil).Files([]*ast.File{f}); err != nil {
panic(err)
fset := token.NewFileSet()
imports := make(testImporter)
conf := Config{Importer: imports}
- mustParse := func(src string) *ast.File {
- f, err := parser.ParseFile(fset, "dummy.go", src, parser.ParseComments)
- if err != nil {
- t.Fatal(err)
- }
- return f
- }
var info Info
makePkg := func(path string, files ...*ast.File) {
var err error
}
}
- makePkg("lib", mustParse("package lib; var X int"))
+ makePkg("lib", mustParse(fset, "", "package lib; var X int"))
// Each /*name=kind:line*/ comment makes the test look up the
// name at that point and checks that it resolves to a decl of
// the specified kind and line number. "undef" means undefined.
`
info.Uses = make(map[*ast.Ident]Object)
- f := mustParse(mainSrc)
+ f := mustParse(fset, "", mainSrc)
makePkg("main", f)
mainScope := imports["main"].Scope()
rx := regexp.MustCompile(`^/\*(\w*)=([\w:]*)\*/$`)
}
for _, test := range tests {
- pkg, err := pkgFor("test", "package p;"+test.src, nil)
+ pkg, err := typecheck("test", "package p;"+test.src, nil)
if err != nil {
t.Errorf("%s: incorrect test case: %s", test.src, err)
continue
func TestIssue15305(t *testing.T) {
const src = "package p; func f() int16; var _ = f(undef)"
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "issue15305.go", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "issue15305.go", src)
conf := Config{
Error: func(err error) {}, // allow errors
}
{`struct{x, y int; z complex128}{}`, `struct{x int; y int; z complex128}`},
} {
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, test.lit, "package p; var _ = "+test.lit, 0)
- if err != nil {
- t.Fatalf("%s: %v", test.lit, err)
- }
-
- info := &Info{
- Types: make(map[ast.Expr]TypeAndValue),
- }
- if _, err = new(Config).Check("p", fset, []*ast.File{f}, info); err != nil {
+ f := mustParse(fset, test.lit, "package p; var _ = "+test.lit)
+ types := make(map[ast.Expr]TypeAndValue)
+ if _, err := new(Config).Check("p", fset, []*ast.File{f}, &Info{Types: types}); err != nil {
t.Fatalf("%s: %v", test.lit, err)
}
cmptype := func(x ast.Expr, want string) {
- tv, ok := info.Types[x]
+ tv, ok := types[x]
if !ok {
t.Errorf("%s: no Types entry found", test.lit)
return
`
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "src", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "src", src)
info := &Info{
Defs: make(map[*ast.Ident]Object),
}
- if _, err = new(Config).Check("p", fset, []*ast.File{f}, info); err != nil {
+ if _, err := new(Config).Check("p", fset, []*ast.File{f}, info); err != nil {
t.Fatal(err)
}
func f(x T) T { return foo.F(x) }
`
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "src", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "src", src)
files := []*ast.File{f}
// type-check using all possible importers
func TestInstantiate(t *testing.T) {
// eventually we like more tests but this is a start
const src = "package p; type T[P any] *T[P]"
- pkg, err := pkgFor(".", src, nil)
+ pkg, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
src := "package p; " + test.src
- pkg, err := pkgFor(".", src, nil)
+ pkg, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
conf := Config{Importer: imports}
makePkg := func(src string) {
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "", src)
name := f.Name.Name
pkg, err := conf.Check(name, fset, []*ast.File{f}, nil)
if err != nil {
Defs: make(map[*ast.Ident]Object),
}
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "p.go", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "p.go", src)
conf := Config{}
pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
if err != nil {
`
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "p.go", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "p.go", src)
conf := Config{Error: func(error) {}}
pkg, _ := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
func (V4) M()
`
- pkg, err := pkgFor("p.go", src, nil)
+ pkg, err := typecheck("p.go", src, nil)
if err != nil {
t.Fatal(err)
}
func Unused() { {}; {{ var x int; _ = x }} } // make sure empty block scopes get printed
`},
} {
- f, err := parser.ParseFile(fset, file.name, file.input, 0)
- if err != nil {
- log.Fatal(err)
- }
- files = append(files, f)
+ files = append(files, mustParse(fset, file.name, file.input))
}
// Type-check a package consisting of these files.
return fib(x-1) - fib(x-2)
}`
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "fib.go", input, 0)
- if err != nil {
- log.Fatal(err)
- }
+ f := mustParse(fset, "fib.go", input)
// Type-check the package.
// We create an empty map for each kind of input
}
for _, test := range tests {
- pkg, err := pkgFor(".", test.src, nil)
+ pkg, err := typecheck(".", test.src, nil)
if err != nil {
t.Fatal(err)
}
func TestInstantiateNonEquality(t *testing.T) {
const src = "package p; type T[P any] int"
- pkg1, err := pkgFor(".", src, nil)
+ pkg1, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
- pkg2, err := pkgFor(".", src, nil)
+ pkg2, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
for _, test := range tests {
src := prefix + test.decl
- pkg, err := pkgFor(".", src, nil)
+ pkg, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
var _ T[int]
`
- pkg, err := pkgFor(".", src, nil)
+ pkg, err := typecheck(".", src, nil)
if err != nil {
t.Fatal(err)
}
"fmt"
"go/ast"
"go/importer"
- "go/parser"
"go/token"
"internal/testenv"
"sort"
. "go/types"
)
-func mustParse(t *testing.T, src string) *ast.File {
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatal(err)
- }
- return f
-}
func TestIssue5770(t *testing.T) {
- f := mustParse(t, `package p; type S struct{T}`)
+ f := mustParse(fset, "", `package p; type S struct{T}`)
conf := Config{Importer: importer.Default()}
_, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // do not crash
const want = "undefined: T"
_ = (interface{})(nil)
)`
types := make(map[ast.Expr]TypeAndValue)
- mustTypecheck(t, "p", src, &Info{Types: types})
+ mustTypecheck("p", src, &Info{Types: types})
for x, tv := range types {
var want Type
}
`
types := make(map[ast.Expr]TypeAndValue)
- mustTypecheck(t, "p", src, &Info{Types: types})
+ mustTypecheck("p", src, &Info{Types: types})
want := Typ[Int]
n := 0
func (T) m() (res bool) { return }
type T struct{} // receiver type after method declaration
`
- f := mustParse(t, src)
+ f := mustParse(fset, "", src)
var conf Config
defs := make(map[*ast.Ident]Object)
_, _, _ = x, y, z // uses x, y, z
}
`
- f := mustParse(t, src)
+ f := mustParse(fset, "", src)
const want = `L3 defs func p._()
L4 defs const w untyped int
}
`
f := func(test, src string) {
- f := mustParse(t, src)
+ f := mustParse(fset, "", src)
cfg := Config{Importer: importer.Default()}
info := Info{Uses: make(map[*ast.Ident]Object)}
_, err := cfg.Check("main", fset, []*ast.File{f}, &info)
}
func TestIssue22525(t *testing.T) {
- f := mustParse(t, `package p; func f() { var a, b, c, d, e int }`)
+ f := mustParse(fset, "", `package p; func f() { var a, b, c, d, e int }`)
got := "\n"
conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
`struct { *I }`,
`struct { a int; b Missing; *Missing }`,
} {
- f := mustParse(t, prefix+src)
+ f := mustParse(fset, "", prefix+src)
cfg := Config{Importer: importer.Default(), Error: func(err error) {}}
info := &Info{Types: make(map[ast.Expr]TypeAndValue)}
// compute original file ASTs
var orig [len(sources)]*ast.File
for i, src := range sources {
- orig[i] = mustParse(t, src)
+ orig[i] = mustParse(fset, "", src)
}
// run the test for all order permutations of the incoming files
}
func TestIssue29029(t *testing.T) {
- f1 := mustParse(t, `package p; type A interface { M() }`)
- f2 := mustParse(t, `package p; var B interface { A }`)
+ f1 := mustParse(fset, "", `package p; type A interface { M() }`)
+ f2 := mustParse(fset, "", `package p; var B interface { A }`)
// printInfo prints the *Func definitions recorded in info, one *Func per line.
printInfo := func(info *Info) string {
const asrc = `package a; type I interface{ M() }; type T struct { F interface { I } }`
const bsrc = `package b; import "a"; type T struct { F interface { a.I } }; var _ = a.T(T{})`
- a, err := pkgFor("a", asrc, nil)
+ a, err := typecheck("a", asrc, nil)
if err != nil {
t.Fatalf("package %s failed to typecheck: %v", a.Name(), err)
}
- bast := mustParse(t, bsrc)
+ bast := mustParse(fset, "", bsrc)
conf := Config{Importer: importHelper{pkg: a}}
b, err := conf.Check(bast.Name.Name, fset, []*ast.File{bast}, nil)
if err != nil {
var pkg *Package
for _, src := range sources {
- f := mustParse(t, src)
+ f := mustParse(fset, "", src)
conf := Config{Importer: importHelper{pkg: pkg}}
res, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
if err != nil {
`
)
- a, err := pkgFor("a", asrc, nil)
+ a, err := typecheck("a", asrc, nil)
if err != nil {
t.Fatalf("package a failed to typecheck: %v", err)
}
for _, test := range tests {
src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val)
types := make(map[ast.Expr]TypeAndValue)
- mustTypecheck(t, "p", src, &Info{Types: types})
+ mustTypecheck("p", src, &Info{Types: types})
var n int
for x, tv := range types {
}
check := func(src string, methods []method, generic bool) {
- pkg, err := pkgFor("test", "package p;"+src, nil)
+ pkg, err := typecheck("test", "package p;"+src, nil)
if err != nil {
t.Errorf("%s: incorrect test case: %s", src, err)
return
import (
"go/ast"
- "go/parser"
"go/token"
"testing"
type Inst = G[int]
`
- pkg, err := pkgFor("p", src, nil)
+ pkg, err := typecheck("p", src, nil)
if err != nil {
b.Fatal(err)
}
`
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "foo.go", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "foo.go", src)
pkg := NewPackage("p", f.Name.Name)
if err := NewChecker(nil, fset, pkg, nil).Files([]*ast.File{f}); err != nil {
t.Fatal(err)
import (
"go/ast"
- "go/parser"
"go/token"
"internal/testenv"
"strings"
// type-check src
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatalf("parse failed: %s", err)
- }
+ f := mustParse(fset, "", src)
var conf Config
pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
if err != nil {
for _, test := range testObjects {
src := "package p; " + test.src
- pkg, err := makePkg(src)
+ pkg, err := typecheck(filename, src, nil)
if err != nil {
t.Errorf("%s: %s", src, err)
continue
"fmt"
"go/ast"
"go/importer"
- "go/parser"
"go/token"
"internal/testenv"
"sort"
fset := token.NewFileSet()
var files []*ast.File
for i, src := range sources {
- f, err := parser.ParseFile(fset, fmt.Sprintf("sources[%d]", i), src, parser.DeclarationErrors)
- if err != nil {
- t.Fatal(err)
- }
- files = append(files, f)
+ files = append(files, mustParse(fset, fmt.Sprintf("sources[%d]", i), src))
}
// resolve and type-check package AST
import (
"go/ast"
"go/importer"
- "go/parser"
"go/token"
"go/types"
"internal/testenv"
func findStructTypeConfig(t *testing.T, src string, conf *types.Config) *types.Struct {
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "x.go", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "x.go", src)
info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
- _, err = conf.Check("x", fset, []*ast.File{f}, &info)
+ _, err := conf.Check("x", fset, []*ast.File{f}, &info)
if err != nil {
t.Fatal(err)
}
const _ = unsafe.Offsetof(struct{ x int64 }{}.x)
`
fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "x.go", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(fset, "x.go", src)
info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
conf := types.Config{
Importer: importer.Default(),
Sizes: &types.StdSizes{WordSize: 8, MaxAlign: 8},
}
- _, err = conf.Check("x", fset, []*ast.File{f}, &info)
+ _, err := conf.Check("x", fset, []*ast.File{f}, &info)
if err != nil {
t.Fatal(err)
}
pkgCount := 0
duration := walkPkgDirs(filepath.Join(testenv.GOROOT(t), "src"), func(dir string, filenames []string) {
- typecheck(t, dir, filenames)
+ typecheckFiles(t, dir, filenames)
pkgCount++
}, t.Error)
"crypto/internal/edwards25519/field/_asm": true,
}
-// typecheck typechecks the given package files.
-func typecheck(t *testing.T, path string, filenames []string) {
+// typecheckFiles typechecks the given package files.
+func typecheckFiles(t *testing.T, path string, filenames []string) {
fset := token.NewFileSet()
// parse package files
package types_test
import (
- "go/ast"
- "go/importer"
- "go/parser"
- "go/token"
"internal/testenv"
"testing"
const filename = "<src>"
-func makePkg(src string) (*Package, error) {
- fset := token.NewFileSet()
- file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
- if err != nil {
- return nil, err
- }
- // use the package name as package path
- conf := Config{Importer: importer.Default()}
- return conf.Check(file.Name.Name, fset, []*ast.File{file}, nil)
-}
-
type testEntry struct {
src, str string
}
for _, test := range tests {
src := `package p; import "io"; type _ io.Writer; type T ` + test.src
- pkg, err := makePkg(src)
+ pkg, err := typecheck(filename, src, nil)
if err != nil {
t.Errorf("%s: %s", src, err)
continue
}
func TestQualifiedTypeString(t *testing.T) {
- p, _ := pkgFor("p.go", "package p; type T int", nil)
- q, _ := pkgFor("q.go", "package q", nil)
+ p, _ := typecheck("p.go", "package p; type T int", nil)
+ q, _ := typecheck("q.go", "package q", nil)
pT := p.Scope().Lookup("T").Type()
for _, test := range []struct {