summaryrefslogtreecommitdiff
path: root/libgo/go/go/doc
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/go/doc')
-rw-r--r--libgo/go/go/doc/comment.go16
-rw-r--r--libgo/go/go/doc/doc.go2
-rw-r--r--libgo/go/go/doc/doc_test.go235
-rw-r--r--libgo/go/go/doc/example.go16
-rw-r--r--libgo/go/go/doc/example_test.go6
-rw-r--r--libgo/go/go/doc/exports.go58
-rw-r--r--libgo/go/go/doc/filter.go2
-rw-r--r--libgo/go/go/doc/headscan.go18
-rw-r--r--libgo/go/go/doc/reader.go80
-rw-r--r--libgo/go/go/doc/testdata/benchmark.go4
-rw-r--r--libgo/go/go/doc/testdata/generics.0.golden76
-rw-r--r--libgo/go/go/doc/testdata/generics.1.golden66
-rw-r--r--libgo/go/go/doc/testdata/generics.2.golden76
-rw-r--r--libgo/go/go/doc/testdata/generics.go74
-rw-r--r--libgo/go/go/doc/testdata/testing.0.golden24
-rw-r--r--libgo/go/go/doc/testdata/testing.1.golden40
-rw-r--r--libgo/go/go/doc/testdata/testing.2.golden24
-rw-r--r--libgo/go/go/doc/testdata/testing.go20
18 files changed, 678 insertions, 159 deletions
diff --git a/libgo/go/go/doc/comment.go b/libgo/go/go/doc/comment.go
index 92131a3b83f..a93c05fbb7e 100644
--- a/libgo/go/go/doc/comment.go
+++ b/libgo/go/go/doc/comment.go
@@ -236,26 +236,24 @@ func heading(line string) string {
// allow "'" for possessive "'s" only
for b := line; ; {
- i := strings.IndexRune(b, '\'')
- if i < 0 {
+ var ok bool
+ if _, b, ok = strings.Cut(b, "'"); !ok {
break
}
- if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') {
- return "" // not followed by "s "
+ if b != "s" && !strings.HasPrefix(b, "s ") {
+ return "" // ' not followed by s and then end-of-word
}
- b = b[i+2:]
}
// allow "." when followed by non-space
for b := line; ; {
- i := strings.IndexRune(b, '.')
- if i < 0 {
+ var ok bool
+ if _, b, ok = strings.Cut(b, "."); !ok {
break
}
- if i+1 >= len(b) || b[i+1] == ' ' {
+ if b == "" || strings.HasPrefix(b, " ") {
return "" // not followed by non-space
}
- b = b[i+1:]
}
return line
diff --git a/libgo/go/go/doc/doc.go b/libgo/go/go/doc/doc.go
index 79d38998e7b..5ab854d084b 100644
--- a/libgo/go/go/doc/doc.go
+++ b/libgo/go/go/doc/doc.go
@@ -157,7 +157,7 @@ func New(pkg *ast.Package, importPath string, mode Mode) *Package {
// NewFromFiles takes ownership of the AST files and may edit them,
// unless the PreserveAST Mode bit is on.
//
-func NewFromFiles(fset *token.FileSet, files []*ast.File, importPath string, opts ...interface{}) (*Package, error) {
+func NewFromFiles(fset *token.FileSet, files []*ast.File, importPath string, opts ...any) (*Package, error) {
// Check for invalid API usage.
if fset == nil {
panic(fmt.Errorf("doc.NewFromFiles: no token.FileSet provided (fset == nil)"))
diff --git a/libgo/go/go/doc/doc_test.go b/libgo/go/go/doc/doc_test.go
index cbdca62aa1d..00cb08512a8 100644
--- a/libgo/go/go/doc/doc_test.go
+++ b/libgo/go/go/doc/doc_test.go
@@ -16,6 +16,7 @@ import (
"os"
"path/filepath"
"regexp"
+ "runtime"
"strings"
"testing"
"text/template"
@@ -38,7 +39,7 @@ func readTemplate(filename string) *template.Template {
return template.Must(t.ParseFiles(filepath.Join(dataDir, filename)))
}
-func nodeFmt(node interface{}, fset *token.FileSet) string {
+func nodeFmt(node any, fset *token.FileSet) string {
var buf bytes.Buffer
printer.Fprint(&buf, fset, node)
return strings.ReplaceAll(strings.TrimSpace(buf.String()), "\n", "\n\t")
@@ -100,58 +101,56 @@ func test(t *testing.T, mode Mode) {
// test packages
for _, pkg := range pkgs {
- importPath := dataDir + "/" + pkg.Name
- var files []*ast.File
- for _, f := range pkg.Files {
- files = append(files, f)
- }
- doc, err := NewFromFiles(fset, files, importPath, mode)
- if err != nil {
- t.Error(err)
- continue
- }
+ t.Run(pkg.Name, func(t *testing.T) {
+ importPath := dataDir + "/" + pkg.Name
+ var files []*ast.File
+ for _, f := range pkg.Files {
+ files = append(files, f)
+ }
+ doc, err := NewFromFiles(fset, files, importPath, mode)
+ if err != nil {
+ t.Fatal(err)
+ }
- // golden files always use / in filenames - canonicalize them
- for i, filename := range doc.Filenames {
- doc.Filenames[i] = filepath.ToSlash(filename)
- }
+ // golden files always use / in filenames - canonicalize them
+ for i, filename := range doc.Filenames {
+ doc.Filenames[i] = filepath.ToSlash(filename)
+ }
- // print documentation
- var buf bytes.Buffer
- if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil {
- t.Error(err)
- continue
- }
- got := buf.Bytes()
+ // print documentation
+ var buf bytes.Buffer
+ if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil {
+ t.Fatal(err)
+ }
+ got := buf.Bytes()
- // update golden file if necessary
- golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
- if *update {
- err := os.WriteFile(golden, got, 0644)
- if err != nil {
- t.Error(err)
+ // update golden file if necessary
+ golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
+ if *update {
+ err := os.WriteFile(golden, got, 0644)
+ if err != nil {
+ t.Fatal(err)
+ }
}
- continue
- }
- // get golden file
- want, err := os.ReadFile(golden)
- if err != nil {
- t.Error(err)
- continue
- }
+ // get golden file
+ want, err := os.ReadFile(golden)
+ if err != nil {
+ t.Fatal(err)
+ }
- // compare
- if !bytes.Equal(got, want) {
- t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
- }
+ // compare
+ if !bytes.Equal(got, want) {
+ t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
+ }
+ })
}
}
func Test(t *testing.T) {
- test(t, 0)
- test(t, AllDecls)
- test(t, AllMethods)
+ t.Run("default", func(t *testing.T) { test(t, 0) })
+ t.Run("AllDecls", func(t *testing.T) { test(t, AllDecls) })
+ t.Run("AllMethods", func(t *testing.T) { test(t, AllMethods) })
}
func TestAnchorID(t *testing.T) {
@@ -162,3 +161,153 @@ func TestAnchorID(t *testing.T) {
t.Errorf("anchorID(%q) = %q; want %q", in, got, want)
}
}
+
+func TestFuncs(t *testing.T) {
+ if runtime.Compiler == "gccgo" {
+ t.Skip("FIXME skipping for gofrontend: generics")
+ }
+
+ fset := token.NewFileSet()
+ file, err := parser.ParseFile(fset, "funcs.go", strings.NewReader(funcsTestFile), parser.ParseComments)
+ if err != nil {
+ t.Fatal(err)
+ }
+ doc, err := NewFromFiles(fset, []*ast.File{file}, "importPath", Mode(0))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, f := range doc.Funcs {
+ f.Decl = nil
+ }
+ for _, ty := range doc.Types {
+ for _, f := range ty.Funcs {
+ f.Decl = nil
+ }
+ for _, m := range ty.Methods {
+ m.Decl = nil
+ }
+ }
+
+ /* FIXME: Commented out for gofrontend.
+
+ compareFuncs := func(t *testing.T, msg string, got, want *Func) {
+ // ignore Decl and Examples
+ got.Decl = nil
+ got.Examples = nil
+ if !(got.Doc == want.Doc &&
+ got.Name == want.Name &&
+ got.Recv == want.Recv &&
+ got.Orig == want.Orig &&
+ got.Level == want.Level) {
+ t.Errorf("%s:\ngot %+v\nwant %+v", msg, got, want)
+ }
+ }
+
+ compareSlices(t, "Funcs", doc.Funcs, funcsPackage.Funcs, compareFuncs)
+ compareSlices(t, "Types", doc.Types, funcsPackage.Types, func(t *testing.T, msg string, got, want *Type) {
+ if got.Name != want.Name {
+ t.Errorf("%s.Name: got %q, want %q", msg, got.Name, want.Name)
+ } else {
+ compareSlices(t, got.Name+".Funcs", got.Funcs, want.Funcs, compareFuncs)
+ compareSlices(t, got.Name+".Methods", got.Methods, want.Methods, compareFuncs)
+ }
+ })
+ */
+}
+
+/* FIXME: Commented out for gofrontend.
+
+func compareSlices[E any](t *testing.T, name string, got, want []E, compareElem func(*testing.T, string, E, E)) {
+ if len(got) != len(want) {
+ t.Errorf("%s: got %d, want %d", name, len(got), len(want))
+ }
+ for i := 0; i < len(got) && i < len(want); i++ {
+ compareElem(t, fmt.Sprintf("%s[%d]", name, i), got[i], want[i])
+ }
+}
+
+*/
+
+const funcsTestFile = `
+package funcs
+
+func F() {}
+
+type S1 struct {
+ S2 // embedded, exported
+ s3 // embedded, unexported
+}
+
+func NewS1() S1 {return S1{} }
+func NewS1p() *S1 { return &S1{} }
+
+func (S1) M1() {}
+func (r S1) M2() {}
+func(S1) m3() {} // unexported not shown
+func (*S1) P1() {} // pointer receiver
+
+type S2 int
+func (S2) M3() {} // shown on S2
+
+type s3 int
+func (s3) M4() {} // shown on S1
+
+type G1[T any] struct {
+ *s3
+}
+
+func NewG1[T any]() G1[T] { return G1[T]{} }
+
+func (G1[T]) MG1() {}
+func (*G1[U]) MG2() {}
+
+type G2[T, U any] struct {}
+
+func NewG2[T, U any]() G2[T, U] { return G2[T, U]{} }
+
+func (G2[T, U]) MG3() {}
+func (*G2[A, B]) MG4() {}
+
+
+`
+
+var funcsPackage = &Package{
+ Funcs: []*Func{{Name: "F"}},
+ Types: []*Type{
+ {
+ Name: "G1",
+ Funcs: []*Func{{Name: "NewG1"}},
+ Methods: []*Func{
+ {Name: "M4", Recv: "G1", // TODO: synthesize a param for G1?
+ Orig: "s3", Level: 1},
+ {Name: "MG1", Recv: "G1[T]", Orig: "G1[T]", Level: 0},
+ {Name: "MG2", Recv: "*G1[U]", Orig: "*G1[U]", Level: 0},
+ },
+ },
+ {
+ Name: "G2",
+ Funcs: []*Func{{Name: "NewG2"}},
+ Methods: []*Func{
+ {Name: "MG3", Recv: "G2[T, U]", Orig: "G2[T, U]", Level: 0},
+ {Name: "MG4", Recv: "*G2[A, B]", Orig: "*G2[A, B]", Level: 0},
+ },
+ },
+ {
+ Name: "S1",
+ Funcs: []*Func{{Name: "NewS1"}, {Name: "NewS1p"}},
+ Methods: []*Func{
+ {Name: "M1", Recv: "S1", Orig: "S1", Level: 0},
+ {Name: "M2", Recv: "S1", Orig: "S1", Level: 0},
+ {Name: "M4", Recv: "S1", Orig: "s3", Level: 1},
+ {Name: "P1", Recv: "*S1", Orig: "*S1", Level: 0},
+ },
+ },
+ {
+ Name: "S2",
+ Methods: []*Func{
+ {Name: "M3", Recv: "S2", Orig: "S2", Level: 0},
+ },
+ },
+ },
+}
diff --git a/libgo/go/go/doc/example.go b/libgo/go/go/doc/example.go
index 274000cecb7..0a880cdefb6 100644
--- a/libgo/go/go/doc/example.go
+++ b/libgo/go/go/doc/example.go
@@ -44,13 +44,13 @@ type Example struct {
// identifiers from other packages (or predeclared identifiers, such as
// "int") and the test file does not include a dot import.
// - The entire test file is the example: the file contains exactly one
-// example function, zero test or benchmark functions, and at least one
-// top-level function, type, variable, or constant declaration other
-// than the example function.
+// example function, zero test, fuzz test, or benchmark function, and at
+// least one top-level function, type, variable, or constant declaration
+// other than the example function.
func Examples(testFiles ...*ast.File) []*Example {
var list []*Example
for _, file := range testFiles {
- hasTests := false // file contains tests or benchmarks
+ hasTests := false // file contains tests, fuzz test, or benchmarks
numDecl := 0 // number of non-import declarations in the file
var flist []*Example
for _, decl := range file.Decls {
@@ -64,7 +64,7 @@ func Examples(testFiles ...*ast.File) []*Example {
}
numDecl++
name := f.Name.Name
- if isTest(name, "Test") || isTest(name, "Benchmark") {
+ if isTest(name, "Test") || isTest(name, "Benchmark") || isTest(name, "Fuzz") {
hasTests = true
continue
}
@@ -133,9 +133,9 @@ func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) (output strin
return "", false, false // no suitable comment found
}
-// isTest tells whether name looks like a test, example, or benchmark.
-// It is a Test (say) if there is a character after Test that is not a
-// lower-case letter. (We don't want Testiness.)
+// isTest tells whether name looks like a test, example, fuzz test, or
+// benchmark. It is a Test (say) if there is a character after Test that is not
+// a lower-case letter. (We don't want Testiness.)
func isTest(name, prefix string) bool {
if !strings.HasPrefix(name, prefix) {
return false
diff --git a/libgo/go/go/doc/example_test.go b/libgo/go/go/doc/example_test.go
index cf1b702549e..21b71290f7d 100644
--- a/libgo/go/go/doc/example_test.go
+++ b/libgo/go/go/doc/example_test.go
@@ -307,6 +307,9 @@ func (X) TestBlah() {
func (X) BenchmarkFoo() {
}
+func (X) FuzzFoo() {
+}
+
func Example() {
fmt.Println("Hello, world!")
// Output: Hello, world!
@@ -326,6 +329,9 @@ func (X) TestBlah() {
func (X) BenchmarkFoo() {
}
+func (X) FuzzFoo() {
+}
+
func main() {
fmt.Println("Hello, world!")
}
diff --git a/libgo/go/go/doc/exports.go b/libgo/go/go/doc/exports.go
index 819c030c9bf..671c622205b 100644
--- a/libgo/go/go/doc/exports.go
+++ b/libgo/go/go/doc/exports.go
@@ -79,18 +79,15 @@ func hasExportedName(list []*ast.Ident) bool {
return false
}
-// removeErrorField removes anonymous fields named "error" from an interface.
-// This is called when "error" has been determined to be a local name,
-// not the predeclared type.
-//
-func removeErrorField(ityp *ast.InterfaceType) {
+// removeAnonymousField removes anonymous fields named name from an interface.
+func removeAnonymousField(name string, ityp *ast.InterfaceType) {
list := ityp.Methods.List // we know that ityp.Methods != nil
j := 0
for _, field := range list {
keepField := true
if n := len(field.Names); n == 0 {
// anonymous field
- if fname, _ := baseTypeName(field.Type); fname == "error" {
+ if fname, _ := baseTypeName(field.Type); fname == name {
keepField = false
}
}
@@ -119,16 +116,25 @@ func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp
for _, field := range list {
keepField := false
if n := len(field.Names); n == 0 {
- // anonymous field
+ // anonymous field or embedded type or union element
fname := r.recordAnonymousField(parent, field.Type)
- if token.IsExported(fname) {
- keepField = true
- } else if ityp != nil && fname == "error" {
- // possibly the predeclared error interface; keep
- // it for now but remember this interface so that
- // it can be fixed if error is also defined locally
- keepField = true
- r.remember(ityp)
+ if fname != "" {
+ if token.IsExported(fname) {
+ keepField = true
+ } else if ityp != nil && predeclaredTypes[fname] {
+ // possibly an embedded predeclared type; keep it for now but
+ // remember this interface so that it can be fixed if name is also
+ // defined locally
+ keepField = true
+ r.remember(fname, ityp)
+ }
+ } else {
+ // If we're operating on an interface, assume that this is an embedded
+ // type or union element.
+ //
+ // TODO(rfindley): consider traversing into approximation/unions
+ // elements to see if they are entirely unexported.
+ keepField = ityp != nil
}
} else {
field.Names = filterIdentList(field.Names)
@@ -172,6 +178,17 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) {
// nothing to do
case *ast.ParenExpr:
r.filterType(nil, t.X)
+ case *ast.StarExpr: // possibly an embedded type literal
+ r.filterType(nil, t.X)
+ case *ast.UnaryExpr:
+ if t.Op == token.TILDE { // approximation element
+ r.filterType(nil, t.X)
+ }
+ case *ast.BinaryExpr:
+ if t.Op == token.OR { // union
+ r.filterType(nil, t.X)
+ r.filterType(nil, t.Y)
+ }
case *ast.ArrayType:
r.filterType(nil, t.Elt)
case *ast.StructType:
@@ -179,6 +196,7 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) {
t.Incomplete = true
}
case *ast.FuncType:
+ r.filterParamList(t.TypeParams)
r.filterParamList(t.Params)
r.filterParamList(t.Results)
case *ast.InterfaceType:
@@ -219,12 +237,16 @@ func (r *reader) filterSpec(spec ast.Spec) bool {
}
}
case *ast.TypeSpec:
+ // Don't filter type parameters here, by analogy with function parameters
+ // which are not filtered for top-level function declarations.
if name := s.Name.Name; token.IsExported(name) {
r.filterType(r.lookupType(s.Name.Name), s.Type)
return true
- } else if name == "error" {
- // special case: remember that error is declared locally
- r.errorDecl = true
+ } else if IsPredeclared(name) {
+ if r.shadowedPredecl == nil {
+ r.shadowedPredecl = make(map[string]bool)
+ }
+ r.shadowedPredecl[name] = true
}
}
return false
diff --git a/libgo/go/go/doc/filter.go b/libgo/go/go/doc/filter.go
index a6f243f33e5..9904da150e9 100644
--- a/libgo/go/go/doc/filter.go
+++ b/libgo/go/go/doc/filter.go
@@ -34,6 +34,8 @@ func matchDecl(d *ast.GenDecl, f Filter) bool {
if f(v.Name.Name) {
return true
}
+ // We don't match ordinary parameters in filterFuncs, so by analogy don't
+ // match type parameters here.
switch t := v.Type.(type) {
case *ast.StructType:
if matchFields(t.Fields, f) {
diff --git a/libgo/go/go/doc/headscan.go b/libgo/go/go/doc/headscan.go
index 28cb84f91da..320895e43a4 100644
--- a/libgo/go/go/doc/headscan.go
+++ b/libgo/go/go/doc/headscan.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build ignore
-// +build ignore
/*
The headscan command extracts comment headings from package files;
@@ -23,10 +22,10 @@ import (
"go/doc"
"go/parser"
"go/token"
- "internal/lazyregexp"
"io/fs"
"os"
"path/filepath"
+ "regexp"
"runtime"
"strings"
)
@@ -37,7 +36,7 @@ var (
)
// ToHTML in comment.go assigns a (possibly blank) ID to each heading
-var html_h = lazyregexp.New(`<h3 id="[^"]*">`)
+var html_h = regexp.MustCompile(`<h3 id="[^"]*">`)
const html_endh = "</h3>\n"
@@ -49,19 +48,14 @@ func isGoFile(fi fs.FileInfo) bool {
func appendHeadings(list []string, comment string) []string {
var buf bytes.Buffer
doc.ToHTML(&buf, comment, nil)
- for s := buf.String(); ; {
+ for s := buf.String(); s != ""; {
loc := html_h.FindStringIndex(s)
if len(loc) == 0 {
break
}
- i := loc[1]
- j := strings.Index(s, html_endh)
- if j < 0 {
- list = append(list, s[i:]) // incorrect HTML
- break
- }
- list = append(list, s[i:j])
- s = s[j+len(html_endh):]
+ var inner string
+ inner, s, _ = strings.Cut(s[loc[1]:], html_endh)
+ list = append(list, inner)
}
return list
}
diff --git a/libgo/go/go/doc/reader.go b/libgo/go/go/doc/reader.go
index c277b35e894..de1d4221064 100644
--- a/libgo/go/go/doc/reader.go
+++ b/libgo/go/go/doc/reader.go
@@ -5,11 +5,13 @@
package doc
import (
+ "fmt"
"go/ast"
"go/token"
"internal/lazyregexp"
"sort"
"strconv"
+ "strings"
)
// ----------------------------------------------------------------------------
@@ -22,8 +24,8 @@ import (
//
type methodSet map[string]*Func
-// recvString returns a string representation of recv of the
-// form "T", "*T", or "BADRECV" (if not a proper receiver type).
+// recvString returns a string representation of recv of the form "T", "*T",
+// "T[A, ...]", "*T[A, ...]" or "BADRECV" (if not a proper receiver type).
//
func recvString(recv ast.Expr) string {
switch t := recv.(type) {
@@ -31,10 +33,34 @@ func recvString(recv ast.Expr) string {
return t.Name
case *ast.StarExpr:
return "*" + recvString(t.X)
+ case *ast.IndexExpr:
+ // Generic type with one parameter.
+ return fmt.Sprintf("%s[%s]", recvString(t.X), recvParam(t.Index))
+ case *ast.IndexListExpr:
+ // Generic type with multiple parameters.
+ if len(t.Indices) > 0 {
+ var b strings.Builder
+ b.WriteString(recvString(t.X))
+ b.WriteByte('[')
+ b.WriteString(recvParam(t.Indices[0]))
+ for _, e := range t.Indices[1:] {
+ b.WriteString(", ")
+ b.WriteString(recvParam(e))
+ }
+ b.WriteByte(']')
+ return b.String()
+ }
}
return "BADRECV"
}
+func recvParam(p ast.Expr) string {
+ if id, ok := p.(*ast.Ident); ok {
+ return id.Name
+ }
+ return "BADPARAM"
+}
+
// set creates the corresponding Func for f and adds it to mset.
// If there are multiple f's with the same name, set keeps the first
// one with documentation; conflicts are ignored. The boolean
@@ -101,6 +127,10 @@ func baseTypeName(x ast.Expr) (name string, imported bool) {
switch t := x.(type) {
case *ast.Ident:
return t.Name, false
+ case *ast.IndexExpr:
+ return baseTypeName(t.X)
+ case *ast.IndexListExpr:
+ return baseTypeName(t.X)
case *ast.SelectorExpr:
if _, ok := t.X.(*ast.Ident); ok {
// only possible for qualified type names;
@@ -112,7 +142,7 @@ func baseTypeName(x ast.Expr) (name string, imported bool) {
case *ast.StarExpr:
return baseTypeName(t.X)
}
- return
+ return "", false
}
// An embeddedSet describes a set of embedded types.
@@ -163,9 +193,9 @@ type reader struct {
types map[string]*namedType
funcs methodSet
- // support for package-local error type declarations
- errorDecl bool // if set, type "error" was declared locally
- fixlist []*ast.InterfaceType // list of interfaces containing anonymous field "error"
+ // support for package-local shadowing of predeclared types
+ shadowedPredecl map[string]bool
+ fixmap map[string][]*ast.InterfaceType
}
func (r *reader) isVisible(name string) bool {
@@ -224,8 +254,11 @@ func (r *reader) readDoc(comment *ast.CommentGroup) {
r.doc += "\n" + text
}
-func (r *reader) remember(typ *ast.InterfaceType) {
- r.fixlist = append(r.fixlist, typ)
+func (r *reader) remember(predecl string, typ *ast.InterfaceType) {
+ if r.fixmap == nil {
+ r.fixmap = make(map[string][]*ast.InterfaceType)
+ }
+ r.fixmap[predecl] = append(r.fixmap[predecl], typ)
}
func specNames(specs []ast.Spec) []string {
@@ -418,6 +451,11 @@ func (r *reader) readFunc(fun *ast.FuncDecl) {
factoryType = t.Elt
}
if n, imp := baseTypeName(factoryType); !imp && r.isVisible(n) && !r.isPredeclared(n) {
+ if lookupTypeParam(n, fun.Type.TypeParams) != nil {
+ // Issue #49477: don't associate fun with its type parameter result.
+ // A type parameter is not a defined type.
+ continue
+ }
if t := r.lookupType(n); t != nil {
typ = t
numResultTypes++
@@ -439,6 +477,22 @@ func (r *reader) readFunc(fun *ast.FuncDecl) {
r.funcs.set(fun, r.mode&PreserveAST != 0)
}
+// lookupTypeParam searches for type parameters named name within the tparams
+// field list, returning the relevant identifier if found, or nil if not.
+func lookupTypeParam(name string, tparams *ast.FieldList) *ast.Ident {
+ if tparams == nil {
+ return nil
+ }
+ for _, field := range tparams.List {
+ for _, id := range field.Names {
+ if id.Name == name {
+ return id
+ }
+ }
+ }
+ return nil
+}
+
var (
noteMarker = `([A-Z][A-Z]+)\(([^)]+)\):?` // MARKER(uid), MARKER at least 2 chars, uid at least 1 char
noteMarkerRx = lazyregexp.New(`^[ \t]*` + noteMarker) // MARKER(uid) at text start
@@ -679,10 +733,11 @@ func (r *reader) computeMethodSets() {
}
}
- // if error was declared locally, don't treat it as exported field anymore
- if r.errorDecl {
- for _, ityp := range r.fixlist {
- removeErrorField(ityp)
+ // For any predeclared names that are declared locally, don't treat them as
+ // exported fields anymore.
+ for predecl := range r.shadowedPredecl {
+ for _, ityp := range r.fixmap[predecl] {
+ removeAnonymousField(predecl, ityp)
}
}
}
@@ -869,6 +924,7 @@ func IsPredeclared(s string) bool {
}
var predeclaredTypes = map[string]bool{
+ "any": true,
"bool": true,
"byte": true,
"complex64": true,
diff --git a/libgo/go/go/doc/testdata/benchmark.go b/libgo/go/go/doc/testdata/benchmark.go
index 1d581f057e6..d27bf116aaf 100644
--- a/libgo/go/go/doc/testdata/benchmark.go
+++ b/libgo/go/go/doc/testdata/benchmark.go
@@ -232,7 +232,7 @@ func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks [
runtime.GOMAXPROCS(procs)
b := &B{
common: common{
- signal: make(chan interface{}),
+ signal: make(chan any),
},
benchmark: Benchmark,
}
@@ -285,7 +285,7 @@ func (b *B) trimOutput() {
func Benchmark(f func(b *B)) BenchmarkResult {
b := &B{
common: common{
- signal: make(chan interface{}),
+ signal: make(chan any),
},
benchmark: InternalBenchmark{"", f},
}
diff --git a/libgo/go/go/doc/testdata/generics.0.golden b/libgo/go/go/doc/testdata/generics.0.golden
new file mode 100644
index 00000000000..91c874c84d6
--- /dev/null
+++ b/libgo/go/go/doc/testdata/generics.0.golden
@@ -0,0 +1,76 @@
+// Package generics contains the new syntax supporting generic ...
+PACKAGE generics
+
+IMPORTPATH
+ testdata/generics
+
+FILENAMES
+ testdata/generics.go
+
+FUNCTIONS
+ // AnotherFunc has an implicit constraint interface. Neither type ...
+ func AnotherFunc[T ~struct{ f int }](_ struct{ f int })
+
+ // Func has an instantiated constraint.
+ func Func[T Constraint[string, Type[int]]]()
+
+ // Single is not a factory function.
+ func Single[T any]() *T
+
+ // Slice is not a factory function.
+ func Slice[T any]() []T
+
+
+TYPES
+ // AFuncType demonstrates filtering of parameters and type ...
+ type AFuncType[T ~struct{ f int }] func(_ struct {
+ // contains filtered or unexported fields
+ })
+
+ // Constraint is a constraint interface with two type parameters.
+ type Constraint[P, Q interface{ string | ~int | Type[int] }] interface {
+ ~int | ~byte | Type[string]
+ M() P
+ }
+
+ // NewEmbeddings demonstrates how we filter the new embedded ...
+ type NewEmbeddings interface {
+ string // should not be filtered
+
+ struct {
+ // contains filtered or unexported fields
+ }
+ ~struct {
+ // contains filtered or unexported fields
+ }
+ *struct {
+ // contains filtered or unexported fields
+ }
+ struct {
+ // contains filtered or unexported fields
+ } | ~struct {
+ // contains filtered or unexported fields
+ }
+ // contains filtered or unexported methods
+ }
+
+ // Parameterized types should be shown.
+ type Type[P any] struct {
+ Field P
+ }
+
+ // Variables with an instantiated type should be shown.
+ var X Type[int]
+
+ // Constructors for parameterized types should be shown.
+ func Constructor[lowerCase any]() Type[lowerCase]
+
+ // MethodA uses a different name for its receiver type parameter.
+ func (t Type[A]) MethodA(p A)
+
+ // MethodB has a blank receiver type parameter.
+ func (t Type[_]) MethodB()
+
+ // MethodC has a lower-case receiver type parameter.
+ func (t Type[c]) MethodC()
+
diff --git a/libgo/go/go/doc/testdata/generics.1.golden b/libgo/go/go/doc/testdata/generics.1.golden
new file mode 100644
index 00000000000..923a4ce5d9a
--- /dev/null
+++ b/libgo/go/go/doc/testdata/generics.1.golden
@@ -0,0 +1,66 @@
+// Package generics contains the new syntax supporting generic ...
+PACKAGE generics
+
+IMPORTPATH
+ testdata/generics
+
+FILENAMES
+ testdata/generics.go
+
+FUNCTIONS
+ // AnotherFunc has an implicit constraint interface. Neither type ...
+ func AnotherFunc[T ~struct{ f int }](_ struct{ f int })
+
+ // Func has an instantiated constraint.
+ func Func[T Constraint[string, Type[int]]]()
+
+ // Single is not a factory function.
+ func Single[T any]() *T
+
+ // Slice is not a factory function.
+ func Slice[T any]() []T
+
+
+TYPES
+ // AFuncType demonstrates filtering of parameters and type ...
+ type AFuncType[T ~struct{ f int }] func(_ struct{ f int })
+
+ // Constraint is a constraint interface with two type parameters.
+ type Constraint[P, Q interface{ string | ~int | Type[int] }] interface {
+ ~int | ~byte | Type[string]
+ M() P
+ }
+
+ // NewEmbeddings demonstrates how we filter the new embedded ...
+ type NewEmbeddings interface {
+ string // should not be filtered
+ int16
+ struct{ f int }
+ ~struct{ f int }
+ *struct{ f int }
+ struct{ f int } | ~struct{ f int }
+ }
+
+ // Parameterized types should be shown.
+ type Type[P any] struct {
+ Field P
+ }
+
+ // Variables with an instantiated type should be shown.
+ var X Type[int]
+
+ // Constructors for parameterized types should be shown.
+ func Constructor[lowerCase any]() Type[lowerCase]
+
+ // MethodA uses a different name for its receiver type parameter.
+ func (t Type[A]) MethodA(p A)
+
+ // MethodB has a blank receiver type parameter.
+ func (t Type[_]) MethodB()
+
+ // MethodC has a lower-case receiver type parameter.
+ func (t Type[c]) MethodC()
+
+ // int16 shadows the predeclared type int16.
+ type int16 int
+
diff --git a/libgo/go/go/doc/testdata/generics.2.golden b/libgo/go/go/doc/testdata/generics.2.golden
new file mode 100644
index 00000000000..91c874c84d6
--- /dev/null
+++ b/libgo/go/go/doc/testdata/generics.2.golden
@@ -0,0 +1,76 @@
+// Package generics contains the new syntax supporting generic ...
+PACKAGE generics
+
+IMPORTPATH
+ testdata/generics
+
+FILENAMES
+ testdata/generics.go
+
+FUNCTIONS
+ // AnotherFunc has an implicit constraint interface. Neither type ...
+ func AnotherFunc[T ~struct{ f int }](_ struct{ f int })
+
+ // Func has an instantiated constraint.
+ func Func[T Constraint[string, Type[int]]]()
+
+ // Single is not a factory function.
+ func Single[T any]() *T
+
+ // Slice is not a factory function.
+ func Slice[T any]() []T
+
+
+TYPES
+ // AFuncType demonstrates filtering of parameters and type ...
+ type AFuncType[T ~struct{ f int }] func(_ struct {
+ // contains filtered or unexported fields
+ })
+
+ // Constraint is a constraint interface with two type parameters.
+ type Constraint[P, Q interface{ string | ~int | Type[int] }] interface {
+ ~int | ~byte | Type[string]
+ M() P
+ }
+
+ // NewEmbeddings demonstrates how we filter the new embedded ...
+ type NewEmbeddings interface {
+ string // should not be filtered
+
+ struct {
+ // contains filtered or unexported fields
+ }
+ ~struct {
+ // contains filtered or unexported fields
+ }
+ *struct {
+ // contains filtered or unexported fields
+ }
+ struct {
+ // contains filtered or unexported fields
+ } | ~struct {
+ // contains filtered or unexported fields
+ }
+ // contains filtered or unexported methods
+ }
+
+ // Parameterized types should be shown.
+ type Type[P any] struct {
+ Field P
+ }
+
+ // Variables with an instantiated type should be shown.
+ var X Type[int]
+
+ // Constructors for parameterized types should be shown.
+ func Constructor[lowerCase any]() Type[lowerCase]
+
+ // MethodA uses a different name for its receiver type parameter.
+ func (t Type[A]) MethodA(p A)
+
+ // MethodB has a blank receiver type parameter.
+ func (t Type[_]) MethodB()
+
+ // MethodC has a lower-case receiver type parameter.
+ func (t Type[c]) MethodC()
+
diff --git a/libgo/go/go/doc/testdata/generics.go b/libgo/go/go/doc/testdata/generics.go
new file mode 100644
index 00000000000..ba7187e4dd9
--- /dev/null
+++ b/libgo/go/go/doc/testdata/generics.go
@@ -0,0 +1,74 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package generics contains the new syntax supporting generic programming in
+// Go.
+package generics
+
+// Variables with an instantiated type should be shown.
+var X Type[int]
+
+// Parameterized types should be shown.
+type Type[P any] struct {
+ Field P
+}
+
+// Constructors for parameterized types should be shown.
+func Constructor[lowerCase any]() Type[lowerCase] {
+ return Type[lowerCase]{}
+}
+
+// MethodA uses a different name for its receiver type parameter.
+func (t Type[A]) MethodA(p A) {}
+
+// MethodB has a blank receiver type parameter.
+func (t Type[_]) MethodB() {}
+
+// MethodC has a lower-case receiver type parameter.
+func (t Type[c]) MethodC() {}
+
+// Constraint is a constraint interface with two type parameters.
+type Constraint[P, Q interface{ string | ~int | Type[int] }] interface {
+ ~int | ~byte | Type[string]
+ M() P
+}
+
+// int16 shadows the predeclared type int16.
+type int16 int
+
+// NewEmbeddings demonstrates how we filter the new embedded elements.
+type NewEmbeddings interface {
+ string // should not be filtered
+ int16
+ struct{ f int }
+ ~struct{ f int }
+ *struct{ f int }
+ struct{ f int } | ~struct{ f int }
+}
+
+// Func has an instantiated constraint.
+func Func[T Constraint[string, Type[int]]]() {}
+
+// AnotherFunc has an implicit constraint interface.
+//
+// Neither type parameters nor regular parameters should be filtered.
+func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) {}
+
+// AFuncType demonstrates filtering of parameters and type parameters. Here we
+// don't filter type parameters (to be consistent with function declarations),
+// but DO filter the RHS.
+type AFuncType[T ~struct{ f int }] func(_ struct{ f int })
+
+// See issue #49477: type parameters should not be interpreted as named types
+// for the purpose of determining whether a function is a factory function.
+
+// Slice is not a factory function.
+func Slice[T any]() []T {
+ return nil
+}
+
+// Single is not a factory function.
+func Single[T any]() *T {
+ return nil
+}
diff --git a/libgo/go/go/doc/testdata/testing.0.golden b/libgo/go/go/doc/testdata/testing.0.golden
index 83cf37cd3a9..61dac8bb66c 100644
--- a/libgo/go/go/doc/testdata/testing.0.golden
+++ b/libgo/go/go/doc/testdata/testing.0.golden
@@ -46,10 +46,10 @@ TYPES
}
// Error is equivalent to Log() followed by Fail().
- func (c *B) Error(args ...interface{})
+ func (c *B) Error(args ...any)
// Errorf is equivalent to Logf() followed by Fail().
- func (c *B) Errorf(format string, args ...interface{})
+ func (c *B) Errorf(format string, args ...any)
// Fail marks the function as having failed but continues ...
func (c *B) Fail()
@@ -61,16 +61,16 @@ TYPES
func (c *B) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
- func (c *B) Fatal(args ...interface{})
+ func (c *B) Fatal(args ...any)
// Fatalf is equivalent to Logf() followed by FailNow().
- func (c *B) Fatalf(format string, args ...interface{})
+ func (c *B) Fatalf(format string, args ...any)
// Log formats its arguments using default formatting, analogous ...
- func (c *B) Log(args ...interface{})
+ func (c *B) Log(args ...any)
// Logf formats its arguments according to the format, analogous ...
- func (c *B) Logf(format string, args ...interface{})
+ func (c *B) Logf(format string, args ...any)
// ResetTimer sets the elapsed benchmark time to zero. It does not ...
func (b *B) ResetTimer()
@@ -125,10 +125,10 @@ TYPES
}
// Error is equivalent to Log() followed by Fail().
- func (c *T) Error(args ...interface{})
+ func (c *T) Error(args ...any)
// Errorf is equivalent to Logf() followed by Fail().
- func (c *T) Errorf(format string, args ...interface{})
+ func (c *T) Errorf(format string, args ...any)
// Fail marks the function as having failed but continues ...
func (c *T) Fail()
@@ -140,16 +140,16 @@ TYPES
func (c *T) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
- func (c *T) Fatal(args ...interface{})
+ func (c *T) Fatal(args ...any)
// Fatalf is equivalent to Logf() followed by FailNow().
- func (c *T) Fatalf(format string, args ...interface{})
+ func (c *T) Fatalf(format string, args ...any)
// Log formats its arguments using default formatting, analogous ...
- func (c *T) Log(args ...interface{})
+ func (c *T) Log(args ...any)
// Logf formats its arguments according to the format, analogous ...
- func (c *T) Logf(format string, args ...interface{})
+ func (c *T) Logf(format string, args ...any)
// Parallel signals that this test is to be run in parallel with ...
func (t *T) Parallel()
diff --git a/libgo/go/go/doc/testdata/testing.1.golden b/libgo/go/go/doc/testdata/testing.1.golden
index b9d14517a9c..1655af11a8c 100644
--- a/libgo/go/go/doc/testdata/testing.1.golden
+++ b/libgo/go/go/doc/testdata/testing.1.golden
@@ -119,10 +119,10 @@ TYPES
}
// Error is equivalent to Log() followed by Fail().
- func (c *B) Error(args ...interface{})
+ func (c *B) Error(args ...any)
// Errorf is equivalent to Logf() followed by Fail().
- func (c *B) Errorf(format string, args ...interface{})
+ func (c *B) Errorf(format string, args ...any)
// Fail marks the function as having failed but continues ...
func (c *B) Fail()
@@ -134,16 +134,16 @@ TYPES
func (c *B) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
- func (c *B) Fatal(args ...interface{})
+ func (c *B) Fatal(args ...any)
// Fatalf is equivalent to Logf() followed by FailNow().
- func (c *B) Fatalf(format string, args ...interface{})
+ func (c *B) Fatalf(format string, args ...any)
// Log formats its arguments using default formatting, analogous ...
- func (c *B) Log(args ...interface{})
+ func (c *B) Log(args ...any)
// Logf formats its arguments according to the format, analogous ...
- func (c *B) Logf(format string, args ...interface{})
+ func (c *B) Logf(format string, args ...any)
// ResetTimer sets the elapsed benchmark time to zero. It does not ...
func (b *B) ResetTimer()
@@ -221,10 +221,10 @@ TYPES
}
// Error is equivalent to Log() followed by Fail().
- func (c *T) Error(args ...interface{})
+ func (c *T) Error(args ...any)
// Errorf is equivalent to Logf() followed by Fail().
- func (c *T) Errorf(format string, args ...interface{})
+ func (c *T) Errorf(format string, args ...any)
// Fail marks the function as having failed but continues ...
func (c *T) Fail()
@@ -236,16 +236,16 @@ TYPES
func (c *T) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
- func (c *T) Fatal(args ...interface{})
+ func (c *T) Fatal(args ...any)
// Fatalf is equivalent to Logf() followed by FailNow().
- func (c *T) Fatalf(format string, args ...interface{})
+ func (c *T) Fatalf(format string, args ...any)
// Log formats its arguments using default formatting, analogous ...
- func (c *T) Log(args ...interface{})
+ func (c *T) Log(args ...any)
// Logf formats its arguments according to the format, analogous ...
- func (c *T) Logf(format string, args ...interface{})
+ func (c *T) Logf(format string, args ...any)
// Parallel signals that this test is to be run in parallel with ...
func (t *T) Parallel()
@@ -262,15 +262,15 @@ TYPES
failed bool // Test or benchmark has failed.
start time.Time // Time test or benchmark started
duration time.Duration
- self interface{} // To be sent on signal channel when done.
- signal chan interface{} // Output for serial tests.
+ self any // To be sent on signal channel when done.
+ signal chan any // Output for serial tests.
}
// Error is equivalent to Log() followed by Fail().
- func (c *common) Error(args ...interface{})
+ func (c *common) Error(args ...any)
// Errorf is equivalent to Logf() followed by Fail().
- func (c *common) Errorf(format string, args ...interface{})
+ func (c *common) Errorf(format string, args ...any)
// Fail marks the function as having failed but continues ...
func (c *common) Fail()
@@ -282,16 +282,16 @@ TYPES
func (c *common) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
- func (c *common) Fatal(args ...interface{})
+ func (c *common) Fatal(args ...any)
// Fatalf is equivalent to Logf() followed by FailNow().
- func (c *common) Fatalf(format string, args ...interface{})
+ func (c *common) Fatalf(format string, args ...any)
// Log formats its arguments using default formatting, analogous ...
- func (c *common) Log(args ...interface{})
+ func (c *common) Log(args ...any)
// Logf formats its arguments according to the format, analogous ...
- func (c *common) Logf(format string, args ...interface{})
+ func (c *common) Logf(format string, args ...any)
// log generates the output. It's always at the same stack depth.
func (c *common) log(s string)
diff --git a/libgo/go/go/doc/testdata/testing.2.golden b/libgo/go/go/doc/testdata/testing.2.golden
index 83cf37cd3a9..61dac8bb66c 100644
--- a/libgo/go/go/doc/testdata/testing.2.golden
+++ b/libgo/go/go/doc/testdata/testing.2.golden
@@ -46,10 +46,10 @@ TYPES
}
// Error is equivalent to Log() followed by Fail().
- func (c *B) Error(args ...interface{})
+ func (c *B) Error(args ...any)
// Errorf is equivalent to Logf() followed by Fail().
- func (c *B) Errorf(format string, args ...interface{})
+ func (c *B) Errorf(format string, args ...any)
// Fail marks the function as having failed but continues ...
func (c *B) Fail()
@@ -61,16 +61,16 @@ TYPES
func (c *B) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
- func (c *B) Fatal(args ...interface{})
+ func (c *B) Fatal(args ...any)
// Fatalf is equivalent to Logf() followed by FailNow().
- func (c *B) Fatalf(format string, args ...interface{})
+ func (c *B) Fatalf(format string, args ...any)
// Log formats its arguments using default formatting, analogous ...
- func (c *B) Log(args ...interface{})
+ func (c *B) Log(args ...any)
// Logf formats its arguments according to the format, analogous ...
- func (c *B) Logf(format string, args ...interface{})
+ func (c *B) Logf(format string, args ...any)
// ResetTimer sets the elapsed benchmark time to zero. It does not ...
func (b *B) ResetTimer()
@@ -125,10 +125,10 @@ TYPES
}
// Error is equivalent to Log() followed by Fail().
- func (c *T) Error(args ...interface{})
+ func (c *T) Error(args ...any)
// Errorf is equivalent to Logf() followed by Fail().
- func (c *T) Errorf(format string, args ...interface{})
+ func (c *T) Errorf(format string, args ...any)
// Fail marks the function as having failed but continues ...
func (c *T) Fail()
@@ -140,16 +140,16 @@ TYPES
func (c *T) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
- func (c *T) Fatal(args ...interface{})
+ func (c *T) Fatal(args ...any)
// Fatalf is equivalent to Logf() followed by FailNow().
- func (c *T) Fatalf(format string, args ...interface{})
+ func (c *T) Fatalf(format string, args ...any)
// Log formats its arguments using default formatting, analogous ...
- func (c *T) Log(args ...interface{})
+ func (c *T) Log(args ...any)
// Logf formats its arguments according to the format, analogous ...
- func (c *T) Logf(format string, args ...interface{})
+ func (c *T) Logf(format string, args ...any)
// Parallel signals that this test is to be run in parallel with ...
func (t *T) Parallel()
diff --git a/libgo/go/go/doc/testdata/testing.go b/libgo/go/go/doc/testdata/testing.go
index 52810f7a564..80238df283a 100644
--- a/libgo/go/go/doc/testdata/testing.go
+++ b/libgo/go/go/doc/testdata/testing.go
@@ -77,8 +77,8 @@ type common struct {
failed bool // Test or benchmark has failed.
start time.Time // Time test or benchmark started
duration time.Duration
- self interface{} // To be sent on signal channel when done.
- signal chan interface{} // Output for serial tests.
+ self any // To be sent on signal channel when done.
+ signal chan any // Output for serial tests.
}
// Short reports whether the -test.short flag is set.
@@ -167,32 +167,32 @@ func (c *common) log(s string) {
// Log formats its arguments using default formatting, analogous to Println(),
// and records the text in the error log.
-func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
+func (c *common) Log(args ...any) { c.log(fmt.Sprintln(args...)) }
// Logf formats its arguments according to the format, analogous to Printf(),
// and records the text in the error log.
-func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
+func (c *common) Logf(format string, args ...any) { c.log(fmt.Sprintf(format, args...)) }
// Error is equivalent to Log() followed by Fail().
-func (c *common) Error(args ...interface{}) {
+func (c *common) Error(args ...any) {
c.log(fmt.Sprintln(args...))
c.Fail()
}
// Errorf is equivalent to Logf() followed by Fail().
-func (c *common) Errorf(format string, args ...interface{}) {
+func (c *common) Errorf(format string, args ...any) {
c.log(fmt.Sprintf(format, args...))
c.Fail()
}
// Fatal is equivalent to Log() followed by FailNow().
-func (c *common) Fatal(args ...interface{}) {
+func (c *common) Fatal(args ...any) {
c.log(fmt.Sprintln(args...))
c.FailNow()
}
// Fatalf is equivalent to Logf() followed by FailNow().
-func (c *common) Fatalf(format string, args ...interface{}) {
+func (c *common) Fatalf(format string, args ...any) {
c.log(fmt.Sprintf(format, args...))
c.FailNow()
}
@@ -269,7 +269,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
// If all tests pump to the same channel, a bug can occur where a test
// kicks off a goroutine that Fails, yet the test still delivers a completion signal,
// which skews the counting.
- var collector = make(chan interface{})
+ var collector = make(chan any)
numParallel := 0
startParallel := make(chan bool)
@@ -289,7 +289,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
}
t := &T{
common: common{
- signal: make(chan interface{}),
+ signal: make(chan any),
},
name: testName,
startParallel: startParallel,