diff options
Diffstat (limited to 'libgo/go/go/doc')
-rw-r--r-- | libgo/go/go/doc/comment.go | 16 | ||||
-rw-r--r-- | libgo/go/go/doc/doc.go | 2 | ||||
-rw-r--r-- | libgo/go/go/doc/doc_test.go | 235 | ||||
-rw-r--r-- | libgo/go/go/doc/example.go | 16 | ||||
-rw-r--r-- | libgo/go/go/doc/example_test.go | 6 | ||||
-rw-r--r-- | libgo/go/go/doc/exports.go | 58 | ||||
-rw-r--r-- | libgo/go/go/doc/filter.go | 2 | ||||
-rw-r--r-- | libgo/go/go/doc/headscan.go | 18 | ||||
-rw-r--r-- | libgo/go/go/doc/reader.go | 80 | ||||
-rw-r--r-- | libgo/go/go/doc/testdata/benchmark.go | 4 | ||||
-rw-r--r-- | libgo/go/go/doc/testdata/generics.0.golden | 76 | ||||
-rw-r--r-- | libgo/go/go/doc/testdata/generics.1.golden | 66 | ||||
-rw-r--r-- | libgo/go/go/doc/testdata/generics.2.golden | 76 | ||||
-rw-r--r-- | libgo/go/go/doc/testdata/generics.go | 74 | ||||
-rw-r--r-- | libgo/go/go/doc/testdata/testing.0.golden | 24 | ||||
-rw-r--r-- | libgo/go/go/doc/testdata/testing.1.golden | 40 | ||||
-rw-r--r-- | libgo/go/go/doc/testdata/testing.2.golden | 24 | ||||
-rw-r--r-- | libgo/go/go/doc/testdata/testing.go | 20 |
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, |