]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/parser,go/types: hide API changes related to type parameters
authorRob Findley <rfindley@google.com>
Wed, 24 Feb 2021 15:31:11 +0000 (10:31 -0500)
committerRobert Findley <rfindley@google.com>
Tue, 2 Mar 2021 01:50:12 +0000 (01:50 +0000)
While the dev.typeparams branch was merged, the type parameter API is
slated for go1.18. Hide these changes to the go/parser and go/types API.

This was done as follows:
 + For APIs that will probably not be needed for go1.18, simply unexport
   them.
 + For APIs that we expect to export in go1.18, prefix symbols with '_',
   so that the planned (upper-cased) symbol name is apparent.
 + For APIs that must be exported for testing, move both API and tests
   to files guarded by the go1.18 build constraint.
 + parser.ParseTypeParams is unexported and copied wherever it is
   needed.
 + The -G flag is removed from gofmt, replaced by enabling type
   parameters if built with the go1.18 build constraint.

Notably, changes related to type parameters in go/ast are currently left
exported. We're looking at the AST API separately.

The new API diff from 1.16 is:
+pkg go/ast, method (*FuncDecl) IsMethod() bool
+pkg go/ast, method (*ListExpr) End() token.Pos
+pkg go/ast, method (*ListExpr) Pos() token.Pos
+pkg go/ast, type FuncType struct, TParams *FieldList
+pkg go/ast, type ListExpr struct
+pkg go/ast, type ListExpr struct, ElemList []Expr
+pkg go/ast, type TypeSpec struct, TParams *FieldList
+pkg go/types, type Config struct, GoVersion string\f

Change-Id: I1baf67e26279b49092e774309a836c460979774a
Reviewed-on: https://go-review.googlesource.com/c/go/+/295929
Trust: Robert Findley <rfindley@google.com>
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
31 files changed:
src/cmd/gofmt/gofmt.go
src/cmd/gofmt/gofmt_go1.18.go [new file with mode: 0644]
src/cmd/gofmt/gofmt_test.go
src/go/parser/error_test.go
src/go/parser/interface.go
src/go/parser/parser.go
src/go/parser/short_test.go
src/go/printer/printer_test.go
src/go/types/api.go
src/go/types/api_go1.18.go [new file with mode: 0644]
src/go/types/api_go1.18_test.go [new file with mode: 0644]
src/go/types/api_test.go
src/go/types/builtins.go
src/go/types/call.go
src/go/types/check.go
src/go/types/check_test.go
src/go/types/decl.go
src/go/types/expr.go
src/go/types/infer.go
src/go/types/lookup.go
src/go/types/operand.go
src/go/types/predicates.go
src/go/types/sanitize.go
src/go/types/scope.go
src/go/types/sizes.go
src/go/types/stmt.go
src/go/types/subst.go
src/go/types/type.go
src/go/types/typestring.go
src/go/types/typexpr.go
src/go/types/unify.go

index b82aa7e7a9357daa014ed8eb59d195b86af959c8..95f537d91e59bafad11258fd7bccd00e81e97abe 100644 (file)
@@ -26,13 +26,16 @@ import (
 
 var (
        // main operation modes
-       list            = flag.Bool("l", false, "list files whose formatting differs from gofmt's")
-       write           = flag.Bool("w", false, "write result to (source) file instead of stdout")
-       rewriteRule     = flag.String("r", "", "rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')")
-       simplifyAST     = flag.Bool("s", false, "simplify code")
-       doDiff          = flag.Bool("d", false, "display diffs instead of rewriting files")
-       allErrors       = flag.Bool("e", false, "report all errors (not just the first 10 on different lines)")
-       allowTypeParams = flag.Bool("G", false, "allow generic code")
+       list        = flag.Bool("l", false, "list files whose formatting differs from gofmt's")
+       write       = flag.Bool("w", false, "write result to (source) file instead of stdout")
+       rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')")
+       simplifyAST = flag.Bool("s", false, "simplify code")
+       doDiff      = flag.Bool("d", false, "display diffs instead of rewriting files")
+       allErrors   = flag.Bool("e", false, "report all errors (not just the first 10 on different lines)")
+
+       // allowTypeParams controls whether type parameters are allowed in the code
+       // being formatted. It is enabled for go1.18 in gofmt_go1.18.go.
+       allowTypeParams = false
 
        // debugging
        cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
@@ -48,6 +51,10 @@ const (
        //
        // This value is defined in go/printer specifically for go/format and cmd/gofmt.
        printerNormalizeNumbers = 1 << 30
+
+       // parseTypeParams tells go/parser to parse type parameters. Must be kept in
+       // sync with go/parser/interface.go.
+       parseTypeParams parser.Mode = 1 << 30
 )
 
 var (
@@ -72,8 +79,8 @@ func initParserMode() {
        if *allErrors {
                parserMode |= parser.AllErrors
        }
-       if *allowTypeParams {
-               parserMode |= parser.ParseTypeParams
+       if allowTypeParams {
+               parserMode |= parseTypeParams
        }
 }
 
diff --git a/src/cmd/gofmt/gofmt_go1.18.go b/src/cmd/gofmt/gofmt_go1.18.go
new file mode 100644 (file)
index 0000000..be7b46b
--- /dev/null
@@ -0,0 +1,12 @@
+// 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.
+
+//go:build go1.18
+// +build go1.18
+
+package main
+
+func init() {
+       allowTypeParams = true
+}
index 60e4f2e03d2e0e093ba96a24f79b9f34782e85c5..9e2239a6926c9df7da6f1fd54cfe91603f375c88 100644 (file)
@@ -78,7 +78,8 @@ func runTest(t *testing.T, in, out string) {
                        // fake flag - pretend input is from stdin
                        stdin = true
                case "-G":
-                       *allowTypeParams = true
+                       // fake flag - allow parsing type parameters
+                       allowTypeParams = true
                default:
                        t.Errorf("unrecognized flag name: %s", name)
                }
index 8e20b7b468c96d0a920d37a3732e677c3a4e7cc2..3caa3571e6a9f984243f3bac08342beae325383c 100644 (file)
@@ -188,7 +188,7 @@ func TestErrors(t *testing.T) {
                if !d.IsDir() && !strings.HasPrefix(name, ".") && (strings.HasSuffix(name, ".src") || strings.HasSuffix(name, ".go2")) {
                        mode := DeclarationErrors | AllErrors
                        if strings.HasSuffix(name, ".go2") {
-                               mode |= ParseTypeParams
+                               mode |= parseTypeParams
                        }
                        checkErrors(t, filepath.Join(testdata, name), nil, mode, true)
                }
index b8b312463ff93f5225f980c65fd19e541df4a29b..123faaee77b7ac4f23e9bb524f2ebcddd05e188b 100644 (file)
@@ -55,8 +55,14 @@ const (
        Trace                                          // print a trace of parsed productions
        DeclarationErrors                              // report declaration errors
        SpuriousErrors                                 // same as AllErrors, for backward-compatibility
-       ParseTypeParams                                // Placeholder. Will control the parsing of type parameters.
        AllErrors         = SpuriousErrors             // report all errors (not just the first 10 on different lines)
+
+       // parseTypeParams controls the parsing of type parameters. Must be
+       // kept in sync with:
+       //  go/printer/printer_test.go
+       //  go/types/check_test.go
+       //  cmd/gofmt/gofmt.go
+       parseTypeParams = 1 << 30
 )
 
 // ParseFile parses the source code of a single Go source file and returns
index 5c4cea8638d32a8a5266501ee62efbe2fd26b0c7..ed1867b3b3fed452191d10512dba989e66dbb592 100644 (file)
@@ -651,7 +651,7 @@ func (p *parser) parseQualifiedIdent(ident *ast.Ident) ast.Expr {
        }
 
        typ := p.parseTypeName(ident)
-       if p.tok == token.LBRACK && p.mode&ParseTypeParams != 0 {
+       if p.tok == token.LBRACK && p.mode&parseTypeParams != 0 {
                typ = p.parseTypeInstance(typ)
        }
 
@@ -712,7 +712,7 @@ func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Ex
        // TODO(rfindley): consider changing parseRhsOrType so that this function variable
        // is not needed.
        argparser := p.parseRhsOrType
-       if p.mode&ParseTypeParams == 0 {
+       if p.mode&parseTypeParams == 0 {
                argparser = p.parseRhs
        }
        if p.tok != token.RBRACK {
@@ -742,13 +742,13 @@ func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Ex
                        // x [P]E
                        return x, &ast.ArrayType{Lbrack: lbrack, Len: args[0], Elt: elt}
                }
-               if p.mode&ParseTypeParams == 0 {
+               if p.mode&parseTypeParams == 0 {
                        p.error(rbrack, "missing element type in array type expression")
                        return nil, &ast.BadExpr{From: args[0].Pos(), To: args[0].End()}
                }
        }
 
-       if p.mode&ParseTypeParams == 0 {
+       if p.mode&parseTypeParams == 0 {
                p.error(firstComma, "expected ']', found ','")
                return x, &ast.BadExpr{From: args[0].Pos(), To: args[len(args)-1].End()}
        }
@@ -1045,7 +1045,7 @@ func (p *parser) parseParameters(scope *ast.Scope, acceptTParams bool) (tparams,
                defer un(trace(p, "Parameters"))
        }
 
-       if p.mode&ParseTypeParams != 0 && acceptTParams && p.tok == token.LBRACK {
+       if p.mode&parseTypeParams != 0 && acceptTParams && p.tok == token.LBRACK {
                opening := p.pos
                p.next()
                // [T any](params) syntax
@@ -1119,7 +1119,7 @@ func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field {
        x := p.parseTypeName(nil)
        if ident, _ := x.(*ast.Ident); ident != nil {
                switch {
-               case p.tok == token.LBRACK && p.mode&ParseTypeParams != 0:
+               case p.tok == token.LBRACK && p.mode&parseTypeParams != 0:
                        // generic method or embedded instantiated type
                        lbrack := p.pos
                        p.next()
@@ -1171,7 +1171,7 @@ func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field {
        } else {
                // embedded, possibly instantiated type
                typ = x
-               if p.tok == token.LBRACK && p.mode&ParseTypeParams != 0 {
+               if p.tok == token.LBRACK && p.mode&parseTypeParams != 0 {
                        // embedded instantiated interface
                        typ = p.parseTypeInstance(typ)
                }
@@ -1193,7 +1193,7 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
        lbrace := p.expect(token.LBRACE)
        scope := ast.NewScope(nil) // interface scope
        var list []*ast.Field
-       for p.tok == token.IDENT || p.mode&ParseTypeParams != 0 && p.tok == token.TYPE {
+       for p.tok == token.IDENT || p.mode&parseTypeParams != 0 && p.tok == token.TYPE {
                if p.tok == token.IDENT {
                        list = append(list, p.parseMethodSpec(scope))
                } else {
@@ -1289,7 +1289,7 @@ func (p *parser) tryIdentOrType() ast.Expr {
        switch p.tok {
        case token.IDENT:
                typ := p.parseTypeName(nil)
-               if p.tok == token.LBRACK && p.mode&ParseTypeParams != 0 {
+               if p.tok == token.LBRACK && p.mode&parseTypeParams != 0 {
                        typ = p.parseTypeInstance(typ)
                }
                return typ
@@ -1552,7 +1552,7 @@ func (p *parser) parseIndexOrSliceOrInstance(x ast.Expr) ast.Expr {
                return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack}
        }
 
-       if p.mode&ParseTypeParams == 0 {
+       if p.mode&parseTypeParams == 0 {
                p.error(firstComma, "expected ']' or ':', found ','")
                return &ast.BadExpr{From: args[0].Pos(), To: args[len(args)-1].End()}
        }
@@ -2696,7 +2696,7 @@ func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token
                        p.exprLev++
                        x := p.parseExpr(true) // we don't know yet if we're a lhs or rhs expr
                        p.exprLev--
-                       if name0, _ := x.(*ast.Ident); p.mode&ParseTypeParams != 0 && name0 != nil && p.tok != token.RBRACK {
+                       if name0, _ := x.(*ast.Ident); p.mode&parseTypeParams != 0 && name0 != nil && p.tok != token.RBRACK {
                                // generic type [T any];
                                p.parseGenericType(spec, lbrack, name0, token.RBRACK)
                        } else {
index 3676c275597cdb6221cc66f36d3343b16a82ee01..b21dd0aa60f4f2e11d04a32eebda08d29b3d6b8c 100644 (file)
@@ -64,8 +64,8 @@ var valids = []string{
 }
 
 // validWithTParamsOnly holds source code examples that are valid if
-// ParseTypeParams is set, but invalid if not. When checking with the
-// ParseTypeParams set, errors are ignored.
+// parseTypeParams is set, but invalid if not. When checking with the
+// parseTypeParams set, errors are ignored.
 var validWithTParamsOnly = []string{
        `package p; type _ []T[ /* ERROR "expected ';', found '\['" */ int]`,
        `package p; type T[P any /* ERROR "expected ']', found any" */ ] struct { P }`,
@@ -131,10 +131,10 @@ func TestValid(t *testing.T) {
        })
        t.Run("tparams", func(t *testing.T) {
                for _, src := range valids {
-                       checkErrors(t, src, src, DeclarationErrors|AllErrors|ParseTypeParams, false)
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors|parseTypeParams, false)
                }
                for _, src := range validWithTParamsOnly {
-                       checkErrors(t, src, src, DeclarationErrors|AllErrors|ParseTypeParams, false)
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors|parseTypeParams, false)
                }
        })
 }
@@ -142,7 +142,7 @@ func TestValid(t *testing.T) {
 // TestSingle is useful to track down a problem with a single short test program.
 func TestSingle(t *testing.T) {
        const src = `package p; var _ = T[P]{}`
-       checkErrors(t, src, src, DeclarationErrors|AllErrors|ParseTypeParams, true)
+       checkErrors(t, src, src, DeclarationErrors|AllErrors|parseTypeParams, true)
 }
 
 var invalids = []string{
@@ -261,10 +261,10 @@ func TestInvalid(t *testing.T) {
        })
        t.Run("tparams", func(t *testing.T) {
                for _, src := range invalids {
-                       checkErrors(t, src, src, DeclarationErrors|AllErrors|ParseTypeParams, true)
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors|parseTypeParams, true)
                }
                for _, src := range invalidTParamErrs {
-                       checkErrors(t, src, src, DeclarationErrors|AllErrors|ParseTypeParams, true)
+                       checkErrors(t, src, src, DeclarationErrors|AllErrors|parseTypeParams, true)
                }
        })
 }
index 03c4badb04bfa36f00fb7c3a93de499109eaf15b..e03c2df0633d6221ab4615b80556d0db3ea4386a 100644 (file)
@@ -19,6 +19,10 @@ import (
        "time"
 )
 
+// parseTypeParams tells go/parser to parse type parameters. Must be kept in
+// sync with go/parser/interface.go.
+const parseTypeParams parser.Mode = 1 << 30
+
 const (
        dataDir  = "testdata"
        tabwidth = 8
@@ -35,6 +39,7 @@ const (
        rawFormat
        normNumber
        idempotent
+       allowTypeParams
 )
 
 // format parses src, prints the corresponding AST, verifies the resulting
@@ -42,7 +47,11 @@ const (
 // if any.
 func format(src []byte, mode checkMode) ([]byte, error) {
        // parse src
-       f, err := parser.ParseFile(fset, "", src, parser.ParseComments|parser.ParseTypeParams)
+       parseMode := parser.ParseComments
+       if mode&allowTypeParams != 0 {
+               parseMode |= parseTypeParams
+       }
+       f, err := parser.ParseFile(fset, "", src, parseMode)
        if err != nil {
                return nil, fmt.Errorf("parse: %s\n%s", err, src)
        }
@@ -70,7 +79,7 @@ func format(src []byte, mode checkMode) ([]byte, error) {
 
        // make sure formatted output is syntactically correct
        res := buf.Bytes()
-       if _, err := parser.ParseFile(fset, "", res, parser.ParseTypeParams); err != nil {
+       if _, err := parser.ParseFile(fset, "", res, parseTypeParams); err != nil {
                return nil, fmt.Errorf("re-parse: %s\n%s", err, buf.Bytes())
        }
 
@@ -201,13 +210,13 @@ var data = []entry{
        {"linebreaks.input", "linebreaks.golden", idempotent},
        {"expressions.input", "expressions.golden", idempotent},
        {"expressions.input", "expressions.raw", rawFormat | idempotent},
-       {"declarations.input", "declarations.golden", 0},
+       {"declarations.input", "declarations.golden", allowTypeParams},
        {"statements.input", "statements.golden", 0},
        {"slow.input", "slow.golden", idempotent},
        {"complit.input", "complit.x", export},
        {"go2numbers.input", "go2numbers.golden", idempotent},
        {"go2numbers.input", "go2numbers.norm", normNumber | idempotent},
-       {"generics.input", "generics.golden", idempotent},
+       {"generics.input", "generics.golden", idempotent | allowTypeParams},
        {"gobuild1.input", "gobuild1.golden", idempotent},
        {"gobuild2.input", "gobuild2.golden", idempotent},
        {"gobuild3.input", "gobuild3.golden", idempotent},
index 09ac65b81f1117a00946dbb92713989e5ef26964..436c23099b4c17959eb0ca80403e89d2dee15c4f 100644 (file)
@@ -184,11 +184,11 @@ type Info struct {
        // qualified identifiers are collected in the Uses map.
        Types map[ast.Expr]TypeAndValue
 
-       // Inferred maps calls of parameterized functions that use
-       // type inference to the inferred type arguments and signature
+       // _Inferred maps calls of parameterized functions that use
+       // type inference to the _Inferred type arguments and signature
        // of the function called. The recorded "call" expression may be
        // an *ast.CallExpr (as in f(x)), or an *ast.IndexExpr (s in f[T]).
-       Inferred map[ast.Expr]Inferred
+       _Inferred map[ast.Expr]_Inferred
 
        // Defs maps identifiers to the objects they define (including
        // package names, dots "." of dot-imports, and blank "_" identifiers).
@@ -346,9 +346,9 @@ func (tv TypeAndValue) HasOk() bool {
        return tv.mode == commaok || tv.mode == mapindex
 }
 
-// Inferred reports the inferred type arguments and signature
+// _Inferred reports the _Inferred type arguments and signature
 // for a parameterized function call that uses type inference.
-type Inferred struct {
+type _Inferred struct {
        Targs []Type
        Sig   *Signature
 }
diff --git a/src/go/types/api_go1.18.go b/src/go/types/api_go1.18.go
new file mode 100644 (file)
index 0000000..d98f4ef
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+//go:build go1.18
+// +build go1.18
+
+package types
+
+import (
+       "go/ast"
+)
+
+type Inferred = _Inferred
+
+func GetInferred(info *Info) map[ast.Expr]Inferred {
+       return info._Inferred
+}
+
+func SetInferred(info *Info, inferred map[ast.Expr]Inferred) {
+       info._Inferred = inferred
+}
diff --git a/src/go/types/api_go1.18_test.go b/src/go/types/api_go1.18_test.go
new file mode 100644 (file)
index 0000000..bbbf705
--- /dev/null
@@ -0,0 +1,138 @@
+// 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.
+
+//go:build go1.18
+
+package types_test
+
+import (
+       "fmt"
+       "go/ast"
+       "testing"
+
+       . "go/types"
+)
+
+func TestInferredInfo(t *testing.T) {
+       var tests = []struct {
+               src   string
+               fun   string
+               targs []string
+               sig   string
+       }{
+               {genericPkg + `p0; func f[T any](T); func _() { f(42) }`,
+                       `f`,
+                       []string{`int`},
+                       `func(int)`,
+               },
+               {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`,
+                       `f`,
+                       []string{`rune`},
+                       `func(rune) rune`,
+               },
+               {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`,
+                       `f`,
+                       []string{`complex128`},
+                       `func(...complex128) complex128`,
+               },
+               {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`,
+                       `f`,
+                       []string{`float64`, `string`, `byte`},
+                       `func(float64, *string, []byte)`,
+               },
+               {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`,
+                       `f`,
+                       []string{`float64`, `byte`},
+                       `func(float64, *byte, ...[]byte)`,
+               },
+
+               {genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`,
+                       `f`,
+                       []string{`string`, `*string`},
+                       `func(x string)`,
+               },
+               {genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`,
+                       `f`,
+                       []string{`int`, `*int`},
+                       `func(x []int)`,
+               },
+               {genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
+                       `f`,
+                       []string{`int`, `chan<- int`},
+                       `func(x []int)`,
+               },
+               {genericPkg + `s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
+                       `f`,
+                       []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
+                       `func(x []int)`,
+               },
+
+               {genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`,
+                       `f`,
+                       []string{`string`, `*string`},
+                       `func() string`,
+               },
+               {genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
+                       `f`,
+                       []string{`int`, `chan<- int`},
+                       `func() []int`,
+               },
+               {genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
+                       `f`,
+                       []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
+                       `func() []int`,
+               },
+       }
+
+       for _, test := range tests {
+               info := Info{}
+               SetInferred(&info, make(map[ast.Expr]Inferred))
+               name, err := mayTypecheck(t, "InferredInfo", test.src, &info)
+               if err != nil {
+                       t.Errorf("package %s: %v", name, err)
+                       continue
+               }
+
+               // look for inferred type arguments and signature
+               var targs []Type
+               var sig *Signature
+               for call, inf := range GetInferred(&info) {
+                       var fun ast.Expr
+                       switch x := call.(type) {
+                       case *ast.CallExpr:
+                               fun = x.Fun
+                       case *ast.IndexExpr:
+                               fun = x.X
+                       default:
+                               panic(fmt.Sprintf("unexpected call expression type %T", call))
+                       }
+                       if ExprString(fun) == test.fun {
+                               targs = inf.Targs
+                               sig = inf.Sig
+                               break
+                       }
+               }
+               if targs == nil {
+                       t.Errorf("package %s: no inferred information found for %s", name, test.fun)
+                       continue
+               }
+
+               // check that type arguments are correct
+               if len(targs) != len(test.targs) {
+                       t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs))
+                       continue
+               }
+               for i, targ := range targs {
+                       if got := targ.String(); got != test.targs[i] {
+                               t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i])
+                               continue
+                       }
+               }
+
+               // check that signature is correct
+               if got := sig.String(); got != test.sig {
+                       t.Errorf("package %s: got %s; want %s", name, got, test.sig)
+               }
+       }
+}
index 20648f1cf6b091d745f861306fbef0a505d73dff..0226a857bd7e8f3253aa3f145cf61f6dc637c8c7 100644 (file)
@@ -49,7 +49,7 @@ const genericPkg = "package generic_"
 
 func modeForSource(src string) parser.Mode {
        if strings.HasPrefix(src, genericPkg) {
-               return parser.ParseTypeParams
+               return parseTypeParams
        }
        return 0
 }
@@ -377,128 +377,6 @@ func TestTypesInfo(t *testing.T) {
        }
 }
 
-func TestInferredInfo(t *testing.T) {
-       var tests = []struct {
-               src   string
-               fun   string
-               targs []string
-               sig   string
-       }{
-               {genericPkg + `p0; func f[T any](T); func _() { f(42) }`,
-                       `f`,
-                       []string{`int`},
-                       `func(int)`,
-               },
-               {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`,
-                       `f`,
-                       []string{`rune`},
-                       `func(rune) rune`,
-               },
-               {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`,
-                       `f`,
-                       []string{`complex128`},
-                       `func(...complex128) complex128`,
-               },
-               {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`,
-                       `f`,
-                       []string{`float64`, `string`, `byte`},
-                       `func(float64, *string, []byte)`,
-               },
-               {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`,
-                       `f`,
-                       []string{`float64`, `byte`},
-                       `func(float64, *byte, ...[]byte)`,
-               },
-
-               {genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`,
-                       `f`,
-                       []string{`string`, `*string`},
-                       `func(x string)`,
-               },
-               {genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`,
-                       `f`,
-                       []string{`int`, `*int`},
-                       `func(x []int)`,
-               },
-               {genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
-                       `f`,
-                       []string{`int`, `chan<- int`},
-                       `func(x []int)`,
-               },
-               {genericPkg + `s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
-                       `f`,
-                       []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
-                       `func(x []int)`,
-               },
-
-               {genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`,
-                       `f`,
-                       []string{`string`, `*string`},
-                       `func() string`,
-               },
-               {genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
-                       `f`,
-                       []string{`int`, `chan<- int`},
-                       `func() []int`,
-               },
-               {genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
-                       `f`,
-                       []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
-                       `func() []int`,
-               },
-       }
-
-       for _, test := range tests {
-               info := Info{Inferred: make(map[ast.Expr]Inferred)}
-               name, err := mayTypecheck(t, "InferredInfo", test.src, &info)
-               if err != nil {
-                       t.Errorf("package %s: %v", name, err)
-                       continue
-               }
-
-               // look for inferred type arguments and signature
-               var targs []Type
-               var sig *Signature
-               for call, inf := range info.Inferred {
-                       var fun ast.Expr
-                       switch x := call.(type) {
-                       case *ast.CallExpr:
-                               fun = x.Fun
-                       case *ast.IndexExpr:
-                               fun = x.X
-                       default:
-                               panic(fmt.Sprintf("unexpected call expression type %T", call))
-                       }
-                       if ExprString(fun) == test.fun {
-                               targs = inf.Targs
-                               sig = inf.Sig
-                               break
-                       }
-               }
-               if targs == nil {
-                       t.Errorf("package %s: no inferred information found for %s", name, test.fun)
-                       continue
-               }
-
-               // check that type arguments are correct
-               if len(targs) != len(test.targs) {
-                       t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs))
-                       continue
-               }
-               for i, targ := range targs {
-                       if got := targ.String(); got != test.targs[i] {
-                               t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i])
-                               continue
-                       }
-               }
-
-               // check that signature is correct
-               if got := sig.String(); got != test.sig {
-                       t.Errorf("package %s: got %s; want %s", name, got, test.sig)
-               }
-       }
-}
-
 func TestDefsInfo(t *testing.T) {
        var tests = []struct {
                src  string
index d45cd9b2781b32495bf578bf6e661df3f7863f72..3df82fffdae06e84d91b721e246d62a3c454f615 100644 (file)
@@ -179,7 +179,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                                mode = value
                        }
 
-               case *Sum:
+               case *_Sum:
                        if t.is(func(t Type) bool {
                                switch t := under(t).(type) {
                                case *Basic:
@@ -469,7 +469,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                                m = 2
                        case *Map, *Chan:
                                m = 1
-                       case *Sum:
+                       case *_Sum:
                                return t.is(valid)
                        default:
                                return false
@@ -732,8 +732,8 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
 
                // construct a suitable new type parameter
                tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "<type parameter>", nil)
-               ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect
-               tsum := NewSum(rtypes)
+               ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect
+               tsum := _NewSum(rtypes)
                ptyp.bound = &Interface{types: tsum, allMethods: markComplete, allTypes: tsum}
 
                return ptyp
index e56f74137063a8161d9bb3f50f43579011ce126b..bd10f6fbc3dea50525ed19c5c96f0379571966d4 100644 (file)
@@ -128,7 +128,7 @@ func (check *Checker) call(x *operand, call *ast.CallExpr) exprKind {
                                }
                                if t := asInterface(T); t != nil {
                                        check.completeInterface(token.NoPos, t)
-                                       if t.IsConstraint() {
+                                       if t._IsConstraint() {
                                                check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T)
                                                break
                                        }
index 4cc3024de990713ed6c3d10abddbecb1732e214e..69e9466a8b9a879651b4167b8a7bbf6fbc07fe8d 100644 (file)
@@ -396,8 +396,8 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) {
 func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature) {
        assert(call != nil)
        assert(sig != nil)
-       if m := check.Inferred; m != nil {
-               m[call] = Inferred{targs, sig}
+       if m := check._Inferred; m != nil {
+               m[call] = _Inferred{targs, sig}
        }
 }
 
index c92855b3d8004c4ca6e95679e9656ca753704649..9812b3808b919034595ca8bee8b24ac33ec8e41d 100644 (file)
@@ -44,6 +44,10 @@ import (
        . "go/types"
 )
 
+// parseTypeParams tells go/parser to parse type parameters. Must be kept in
+// sync with go/parser/interface.go.
+const parseTypeParams parser.Mode = 1 << 30
+
 var (
        haltOnError = flag.Bool("halt", false, "halt on error")
        listErrors  = flag.Bool("errlist", false, "list errors")
@@ -210,7 +214,7 @@ func checkFiles(t *testing.T, goVersion string, filenames []string, srcs [][]byt
 
        mode := parser.AllErrors
        if strings.HasSuffix(filenames[0], ".go2") {
-               mode |= parser.ParseTypeParams
+               mode |= parseTypeParams
        }
 
        // parse files and collect parser errors
index 1134607e92c2fe35bb61e54746379ff624940728..2eb2c39745935f2c570c6e0e0745cc1a8a88ba8a 100644 (file)
@@ -713,7 +713,7 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam
 
        setBoundAt := func(at int, bound Type) {
                assert(IsInterface(bound))
-               tparams[at].typ.(*TypeParam).bound = bound
+               tparams[at].typ.(*_TypeParam).bound = bound
        }
 
        index := 0
@@ -756,7 +756,7 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam
 func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) []*TypeName {
        for _, name := range names {
                tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil)
-               check.NewTypeParam(tpar, len(tparams), &emptyInterface) // assigns type to tpar as a side-effect
+               check.newTypeParam(tpar, len(tparams), &emptyInterface) // assigns type to tpar as a side-effect
                check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position
                tparams = append(tparams, tpar)
        }
index 9b51ce94b741882672f246822219739f3282d6be..e1b484c4109e4b516dff090a60cb0ced12225eb4 100644 (file)
@@ -660,7 +660,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
                default:
                        return nil, nil, _InvalidUntypedConversion
                }
-       case *Sum:
+       case *_Sum:
                ok := t.is(func(t Type) bool {
                        target, _, _ := check.implicitTypeAndValue(x, t)
                        return target != nil
@@ -1517,7 +1517,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                        x.expr = e
                        return expression
 
-               case *Sum:
+               case *_Sum:
                        // A sum type can be indexed if all of the sum's types
                        // support indexing and have the same index and element
                        // type. Special rules apply for maps in the sum type.
@@ -1549,7 +1549,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                                        tkey = t.key
                                        e = t.elem
                                        nmaps++
-                               case *TypeParam:
+                               case *_TypeParam:
                                        check.errorf(x, 0, "type of %s contains a type parameter - cannot index (implementation restriction)", x)
                                case *instance:
                                        panic("unimplemented")
@@ -1661,7 +1661,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                        valid = true
                        // x.typ doesn't change
 
-               case *Sum, *TypeParam:
+               case *_Sum, *_TypeParam:
                        check.errorf(x, 0, "generic slice expressions not yet implemented")
                        goto Error
                }
index 95bd3cb378d856d2eb114fff924c78e5399a7cd2..4b20836f885267f67e73f677fb4aa85194fef62b 100644 (file)
@@ -98,7 +98,7 @@ func (check *Checker) infer(tparams []*TypeName, params *Tuple, args []*operand)
                // only parameter type it can possibly match against is a *TypeParam.
                // Thus, only keep the indices of generic parameters that are not of
                // composite types and which don't have a type inferred yet.
-               if tpar, _ := par.typ.(*TypeParam); tpar != nil && u.x.at(tpar.index) == nil {
+               if tpar, _ := par.typ.(*_TypeParam); tpar != nil && u.x.at(tpar.index) == nil {
                        indices[j] = i
                        j++
                }
@@ -201,7 +201,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) {
                        }
                }
 
-       case *Sum:
+       case *_Sum:
                return w.isParameterizedList(t.types)
 
        case *Signature:
@@ -243,7 +243,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) {
        case *Named:
                return w.isParameterizedList(t.targs)
 
-       case *TypeParam:
+       case *_TypeParam:
                // t must be one of w.tparams
                return t.index < len(w.tparams) && w.tparams[t.index].typ == t
 
@@ -291,7 +291,7 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type) (types []Type, i
 
        // Unify type parameters with their structural constraints, if any.
        for _, tpar := range tparams {
-               typ := tpar.typ.(*TypeParam)
+               typ := tpar.typ.(*_TypeParam)
                sbound := check.structuralType(typ.bound)
                if sbound != nil {
                        if !u.unify(typ, sbound) {
index a0e7f3cc0dba7fc6fe1bf830259f51e75b126149..3691b1ecaa53f98215513d2aaf4cb1440a2e2dd3 100644 (file)
@@ -107,7 +107,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
                var next []embeddedType // embedded types found at current depth
 
                // look for (pkg, name) in all types at current depth
-               var tpar *TypeParam // set if obj receiver is a type parameter
+               var tpar *_TypeParam // set if obj receiver is a type parameter
                for _, e := range current {
                        typ := e.typ
 
@@ -195,7 +195,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
                                        indirect = e.indirect
                                }
 
-                       case *TypeParam:
+                       case *_TypeParam:
                                // only consider explicit methods in the type parameter bound, not
                                // methods that may be common to all types in the type list.
                                if i, m := lookupMethod(t.Bound().allMethods, pkg, name); m != nil {
index 8f9c9d09bfc6ac115da88fb285a7210b63e56651..8344c059c43225452b06483ba3644cba7064d9a9 100644 (file)
@@ -242,7 +242,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
 
        // x is an untyped value representable by a value of type T.
        if isUntyped(Vu) {
-               if t, ok := Tu.(*Sum); ok {
+               if t, ok := Tu.(*_Sum); ok {
                        return t.is(func(t Type) bool {
                                // TODO(gri) this could probably be more efficient
                                ok, _ := x.assignableTo(check, t, reason)
index 0ff8fcbbf71ddf0a12f22b42d439c9bd87b507f7..7bb026414f8c36366b47cf164236662dbe5e9dc9 100644 (file)
@@ -14,7 +14,7 @@ import (
 // isNamed may be called with types that are not fully set up.
 func isNamed(typ Type) bool {
        switch typ.(type) {
-       case *Basic, *Named, *TypeParam, *instance:
+       case *Basic, *Named, *_TypeParam, *instance:
                return true
        }
        return false
@@ -32,7 +32,7 @@ func is(typ Type, what BasicInfo) bool {
        switch t := optype(typ).(type) {
        case *Basic:
                return t.info&what != 0
-       case *Sum:
+       case *_Sum:
                return t.is(func(typ Type) bool { return is(typ, what) })
        }
        return false
@@ -109,7 +109,7 @@ func comparable(T Type, seen map[Type]bool) bool {
        //
        // is not comparable because []byte is not comparable.
        if t := asTypeParam(T); t != nil && optype(t) == theTop {
-               return t.Bound().IsComparable()
+               return t.Bound()._IsComparable()
        }
 
        switch t := optype(T).(type) {
@@ -128,13 +128,13 @@ func comparable(T Type, seen map[Type]bool) bool {
                return true
        case *Array:
                return comparable(t.elem, seen)
-       case *Sum:
+       case *_Sum:
                pred := func(t Type) bool {
                        return comparable(t, seen)
                }
                return t.is(pred)
-       case *TypeParam:
-               return t.Bound().IsComparable()
+       case *_TypeParam:
+               return t.Bound()._IsComparable()
        }
        return false
 }
@@ -146,7 +146,7 @@ func hasNil(typ Type) bool {
                return t.kind == UnsafePointer
        case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
                return true
-       case *Sum:
+       case *_Sum:
                return t.is(hasNil)
        }
        return false
@@ -265,14 +265,14 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
                                check.identical0(x.results, y.results, cmpTags, p)
                }
 
-       case *Sum:
+       case *_Sum:
                // Two sum types are identical if they contain the same types.
                // (Sum types always consist of at least two types. Also, the
                // the set (list) of types in a sum type consists of unique
                // types - each type appears exactly once. Thus, two sum types
                // must contain the same number of types to have chance of
                // being equal.
-               if y, ok := y.(*Sum); ok && len(x.types) == len(y.types) {
+               if y, ok := y.(*_Sum); ok && len(x.types) == len(y.types) {
                        // Every type in x.types must be in y.types.
                        // Quadratic algorithm, but probably good enough for now.
                        // TODO(gri) we need a fast quick type ID/hash for all types.
@@ -370,7 +370,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
                        return x.obj == y.obj
                }
 
-       case *TypeParam:
+       case *_TypeParam:
                // nothing to do (x and y being equal is caught in the very beginning of this function)
 
        // case *instance:
@@ -397,7 +397,7 @@ func (check *Checker) identicalTParams(x, y []*TypeName, cmpTags bool, p *ifaceP
        }
        for i, x := range x {
                y := y[i]
-               if !check.identical0(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) {
+               if !check.identical0(x.typ.(*_TypeParam).bound, y.typ.(*_TypeParam).bound, cmpTags, p) {
                        return false
                }
        }
index 3a6896c5c2f7a4b01e89d0183bebeeb65998b8cc..3429867321bb882502f6168b0c2459075cb75798 100644 (file)
@@ -24,7 +24,7 @@ func sanitizeInfo(info *Info) {
                }
        }
 
-       for e, inf := range info.Inferred {
+       for e, inf := range info._Inferred {
                changed := false
                for i, targ := range inf.Targs {
                        if typ := s.typ(targ); typ != targ {
@@ -37,7 +37,7 @@ func sanitizeInfo(info *Info) {
                        changed = true
                }
                if changed {
-                       info.Inferred[e] = inf
+                       info._Inferred[e] = inf
                }
        }
 
@@ -102,7 +102,7 @@ func (s sanitizer) typ(typ Type) Type {
                s.tuple(t.params)
                s.tuple(t.results)
 
-       case *Sum:
+       case *_Sum:
                s.typeList(t.types)
 
        case *Interface:
@@ -135,7 +135,7 @@ func (s sanitizer) typ(typ Type) Type {
                s.typeList(t.targs)
                s.funcList(t.methods)
 
-       case *TypeParam:
+       case *_TypeParam:
                if bound := s.typ(t.bound); bound != t.bound {
                        t.bound = bound
                }
index 157b1b70661d1e6fee217d54d06cd0ca83b6209f..26c28d1c4e3c46437d8640b893137ef3b0ccdcef 100644 (file)
@@ -108,13 +108,13 @@ func (s *Scope) Insert(obj Object) Object {
        return nil
 }
 
-// Squash merges s with its parent scope p by adding all
+// squash merges s with its parent scope p by adding all
 // objects of s to p, adding all children of s to the
 // children of p, and removing s from p's children.
 // The function f is called for each object obj in s which
 // has an object alt in p. s should be discarded after
 // having been squashed.
-func (s *Scope) Squash(err func(obj, alt Object)) {
+func (s *Scope) squash(err func(obj, alt Object)) {
        p := s.parent
        assert(p != nil)
        for _, obj := range s.elems {
index e8377a4f9291756f79c75a6f6c5f96aa966d6ca5..67052bb816e0935167cd0e204731a247e2a6a50b 100644 (file)
@@ -148,7 +148,7 @@ func (s *StdSizes) Sizeof(T Type) int64 {
                }
                offsets := s.Offsetsof(t.fields)
                return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
-       case *Sum:
+       case *_Sum:
                panic("Sizeof unimplemented for type sum")
        case *Interface:
                return s.WordSize * 2
index 82c21c2a7a62ae0fa3de00d6312d2a253a14ba43..27da198a850aa3fdc126c65a039576bef67c4947 100644 (file)
@@ -907,7 +907,7 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) {
                        msg = "send-only channel"
                }
                return typ.elem, Typ[Invalid], msg
-       case *Sum:
+       case *_Sum:
                first := true
                var key, val Type
                var msg string
index ed274885034ae4b9b84281790aba969d345b525c..931375f1f2b9873304975e85b5eb78991273e002 100644 (file)
@@ -22,21 +22,21 @@ type substMap struct {
        // TODO(gri) rewrite that code, get rid of this field, and make this
        //           struct just the map (proj)
        targs []Type
-       proj  map[*TypeParam]Type
+       proj  map[*_TypeParam]Type
 }
 
 // makeSubstMap creates a new substitution map mapping tpars[i] to targs[i].
 // If targs[i] is nil, tpars[i] is not substituted.
 func makeSubstMap(tpars []*TypeName, targs []Type) *substMap {
        assert(len(tpars) == len(targs))
-       proj := make(map[*TypeParam]Type, len(tpars))
+       proj := make(map[*_TypeParam]Type, len(tpars))
        for i, tpar := range tpars {
                // We must expand type arguments otherwise *instance
                // types end up as components in composite types.
                // TODO(gri) explain why this causes problems, if it does
                targ := expand(targs[i]) // possibly nil
                targs[i] = targ
-               proj[tpar.typ.(*TypeParam)] = targ
+               proj[tpar.typ.(*_TypeParam)] = targ
        }
        return &substMap{targs, proj}
 }
@@ -49,7 +49,7 @@ func (m *substMap) empty() bool {
        return len(m.proj) == 0
 }
 
-func (m *substMap) lookup(tpar *TypeParam) Type {
+func (m *substMap) lookup(tpar *_TypeParam) Type {
        if t := m.proj[tpar]; t != nil {
                return t
        }
@@ -121,7 +121,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist
 
        // check bounds
        for i, tname := range tparams {
-               tpar := tname.typ.(*TypeParam)
+               tpar := tname.typ.(*_TypeParam)
                iface := tpar.Bound()
                if iface.Empty() {
                        continue // no type bound
@@ -222,7 +222,7 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap) Type {
        switch t := typ.(type) {
        case *Basic:
                return typ // nothing to do
-       case *TypeParam:
+       case *_TypeParam:
                return smap.lookup(t)
        }
 
@@ -293,13 +293,13 @@ func (subst *subster) typ(typ Type) Type {
                        }
                }
 
-       case *Sum:
+       case *_Sum:
                types, copied := subst.typeList(t.types)
                if copied {
                        // Don't do it manually, with a Sum literal: the new
                        // types list may not be unique and NewSum may remove
                        // duplicates.
-                       return NewSum(types)
+                       return _NewSum(types)
                }
 
        case *Interface:
@@ -389,7 +389,7 @@ func (subst *subster) typ(typ Type) Type {
 
                // create a new named type and populate caches to avoid endless recursion
                tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil)
-               named := subst.check.NewNamed(tname, t.underlying, t.methods) // method signatures are updated lazily
+               named := subst.check.newNamed(tname, t.underlying, t.methods) // method signatures are updated lazily
                named.tparams = t.tparams                                     // new type is still parameterized
                named.targs = newTargs
                subst.check.typMap[h] = named
@@ -402,7 +402,7 @@ func (subst *subster) typ(typ Type) Type {
 
                return named
 
-       case *TypeParam:
+       case *_TypeParam:
                return subst.smap.lookup(t)
 
        case *instance:
index 21892c9270d0dab06bf7652e0224baa7692bac82..201da95a581367ca75159c57ab6a5199485fdcc2 100644 (file)
@@ -240,11 +240,11 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
 // contain methods whose receiver type is a different interface.
 func (s *Signature) Recv() *Var { return s.recv }
 
-// TParams returns the type parameters of signature s, or nil.
-func (s *Signature) TParams() []*TypeName { return s.tparams }
+// _TParams returns the type parameters of signature s, or nil.
+func (s *Signature) _TParams() []*TypeName { return s.tparams }
 
-// SetTParams sets the type parameters of signature s.
-func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams }
+// _SetTParams sets the type parameters of signature s.
+func (s *Signature) _SetTParams(tparams []*TypeName) { s.tparams = tparams }
 
 // Params returns the parameters of signature s, or nil.
 func (s *Signature) Params() *Tuple { return s.params }
@@ -255,19 +255,19 @@ func (s *Signature) Results() *Tuple { return s.results }
 // Variadic reports whether the signature s is variadic.
 func (s *Signature) Variadic() bool { return s.variadic }
 
-// A Sum represents a set of possible types.
+// A _Sum represents a set of possible types.
 // Sums are currently used to represent type lists of interfaces
 // and thus the underlying types of type parameters; they are not
 // first class types of Go.
-type Sum struct {
+type _Sum struct {
        types []Type // types are unique
 }
 
-// NewSum returns a new Sum type consisting of the provided
+// _NewSum returns a new Sum type consisting of the provided
 // types if there are more than one. If there is exactly one
 // type, it returns that type. If the list of types is empty
 // the result is nil.
-func NewSum(types []Type) Type {
+func _NewSum(types []Type) Type {
        if len(types) == 0 {
                return nil
        }
@@ -278,7 +278,7 @@ func NewSum(types []Type) Type {
        // current use case of type lists.
        // TODO(gri) Come up with the rules for sum types.
        for _, t := range types {
-               if _, ok := t.(*Sum); ok {
+               if _, ok := t.(*_Sum); ok {
                        panic("sum type contains sum type - unimplemented")
                }
        }
@@ -286,11 +286,11 @@ func NewSum(types []Type) Type {
        if len(types) == 1 {
                return types[0]
        }
-       return &Sum{types: types}
+       return &_Sum{types: types}
 }
 
 // is reports whether all types in t satisfy pred.
-func (s *Sum) is(pred func(Type) bool) bool {
+func (s *_Sum) is(pred func(Type) bool) bool {
        if s == nil {
                return false
        }
@@ -446,8 +446,8 @@ func (t *Interface) Empty() bool {
        }, nil)
 }
 
-// HasTypeList reports whether interface t has a type list, possibly from an embedded type.
-func (t *Interface) HasTypeList() bool {
+// _HasTypeList reports whether interface t has a type list, possibly from an embedded type.
+func (t *Interface) _HasTypeList() bool {
        if t.allMethods != nil {
                // interface is complete - quick test
                return t.allTypes != nil
@@ -458,8 +458,8 @@ func (t *Interface) HasTypeList() bool {
        }, nil)
 }
 
-// IsComparable reports whether interface t is or embeds the predeclared interface "comparable".
-func (t *Interface) IsComparable() bool {
+// _IsComparable reports whether interface t is or embeds the predeclared interface "comparable".
+func (t *Interface) _IsComparable() bool {
        if t.allMethods != nil {
                // interface is complete - quick test
                _, m := lookupMethod(t.allMethods, nil, "==")
@@ -472,8 +472,8 @@ func (t *Interface) IsComparable() bool {
        }, nil)
 }
 
-// IsConstraint reports t.HasTypeList() || t.IsComparable().
-func (t *Interface) IsConstraint() bool {
+// _IsConstraint reports t.HasTypeList() || t.IsComparable().
+func (t *Interface) _IsConstraint() bool {
        if t.allMethods != nil {
                // interface is complete - quick test
                if t.allTypes != nil {
@@ -667,7 +667,7 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
        return typ
 }
 
-func (check *Checker) NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
+func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
        typ := &Named{check: check, obj: obj, orig: underlying, underlying: underlying, methods: methods}
        if obj.typ == nil {
                obj.typ = typ
@@ -681,15 +681,15 @@ func (t *Named) Obj() *TypeName { return t.obj }
 // TODO(gri) Come up with a better representation and API to distinguish
 //           between parameterized instantiated and non-instantiated types.
 
-// TParams returns the type parameters of the named type t, or nil.
+// _TParams returns the type parameters of the named type t, or nil.
 // The result is non-nil for an (originally) parameterized type even if it is instantiated.
-func (t *Named) TParams() []*TypeName { return t.tparams }
+func (t *Named) _TParams() []*TypeName { return t.tparams }
 
-// TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated.
-func (t *Named) TArgs() []Type { return t.targs }
+// _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated.
+func (t *Named) _TArgs() []Type { return t.targs }
 
-// SetTArgs sets the type arguments of Named.
-func (t *Named) SetTArgs(args []Type) { t.targs = args }
+// _SetTArgs sets the type arguments of Named.
+func (t *Named) _SetTArgs(args []Type) { t.targs = args }
 
 // NumMethods returns the number of explicit methods whose receiver is named type t.
 func (t *Named) NumMethods() int { return len(t.methods) }
@@ -715,8 +715,8 @@ func (t *Named) AddMethod(m *Func) {
        }
 }
 
-// A TypeParam represents a type parameter type.
-type TypeParam struct {
+// A _TypeParam represents a type parameter type.
+type _TypeParam struct {
        check *Checker  // for lazy type bound completion
        id    uint64    // unique id
        obj   *TypeName // corresponding type name
@@ -724,10 +724,10 @@ type TypeParam struct {
        bound Type      // *Named or *Interface; underlying type is always *Interface
 }
 
-// NewTypeParam returns a new TypeParam.
-func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
+// newTypeParam returns a new TypeParam.
+func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *_TypeParam {
        assert(bound != nil)
-       typ := &TypeParam{check: check, id: check.nextId, obj: obj, index: index, bound: bound}
+       typ := &_TypeParam{check: check, id: check.nextId, obj: obj, index: index, bound: bound}
        check.nextId++
        if obj.typ == nil {
                obj.typ = typ
@@ -735,7 +735,7 @@ func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypePa
        return typ
 }
 
-func (t *TypeParam) Bound() *Interface {
+func (t *_TypeParam) Bound() *Interface {
        iface := asInterface(t.bound)
        // use the type bound position if we have one
        pos := token.NoPos
@@ -839,40 +839,40 @@ type top struct{}
 var theTop = &top{}
 
 // Type-specific implementations of Underlying.
-func (t *Basic) Underlying() Type     { return t }
-func (t *Array) Underlying() Type     { return t }
-func (t *Slice) Underlying() Type     { return t }
-func (t *Struct) Underlying() Type    { return t }
-func (t *Pointer) Underlying() Type   { return t }
-func (t *Tuple) Underlying() Type     { return t }
-func (t *Signature) Underlying() Type { return t }
-func (t *Sum) Underlying() Type       { return t }
-func (t *Interface) Underlying() Type { return t }
-func (t *Map) Underlying() Type       { return t }
-func (t *Chan) Underlying() Type      { return t }
-func (t *Named) Underlying() Type     { return t.underlying }
-func (t *TypeParam) Underlying() Type { return t }
-func (t *instance) Underlying() Type  { return t }
-func (t *bottom) Underlying() Type    { return t }
-func (t *top) Underlying() Type       { return t }
+func (t *Basic) Underlying() Type      { return t }
+func (t *Array) Underlying() Type      { return t }
+func (t *Slice) Underlying() Type      { return t }
+func (t *Struct) Underlying() Type     { return t }
+func (t *Pointer) Underlying() Type    { return t }
+func (t *Tuple) Underlying() Type      { return t }
+func (t *Signature) Underlying() Type  { return t }
+func (t *_Sum) Underlying() Type       { return t }
+func (t *Interface) Underlying() Type  { return t }
+func (t *Map) Underlying() Type        { return t }
+func (t *Chan) Underlying() Type       { return t }
+func (t *Named) Underlying() Type      { return t.underlying }
+func (t *_TypeParam) Underlying() Type { return t }
+func (t *instance) Underlying() Type   { return t }
+func (t *bottom) Underlying() Type     { return t }
+func (t *top) Underlying() Type        { return t }
 
 // Type-specific implementations of String.
-func (t *Basic) String() string     { return TypeString(t, nil) }
-func (t *Array) String() string     { return TypeString(t, nil) }
-func (t *Slice) String() string     { return TypeString(t, nil) }
-func (t *Struct) String() string    { return TypeString(t, nil) }
-func (t *Pointer) String() string   { return TypeString(t, nil) }
-func (t *Tuple) String() string     { return TypeString(t, nil) }
-func (t *Signature) String() string { return TypeString(t, nil) }
-func (t *Sum) String() string       { return TypeString(t, nil) }
-func (t *Interface) String() string { return TypeString(t, nil) }
-func (t *Map) String() string       { return TypeString(t, nil) }
-func (t *Chan) String() string      { return TypeString(t, nil) }
-func (t *Named) String() string     { return TypeString(t, nil) }
-func (t *TypeParam) String() string { return TypeString(t, nil) }
-func (t *instance) String() string  { return TypeString(t, nil) }
-func (t *bottom) String() string    { return TypeString(t, nil) }
-func (t *top) String() string       { return TypeString(t, nil) }
+func (t *Basic) String() string      { return TypeString(t, nil) }
+func (t *Array) String() string      { return TypeString(t, nil) }
+func (t *Slice) String() string      { return TypeString(t, nil) }
+func (t *Struct) String() string     { return TypeString(t, nil) }
+func (t *Pointer) String() string    { return TypeString(t, nil) }
+func (t *Tuple) String() string      { return TypeString(t, nil) }
+func (t *Signature) String() string  { return TypeString(t, nil) }
+func (t *_Sum) String() string       { return TypeString(t, nil) }
+func (t *Interface) String() string  { return TypeString(t, nil) }
+func (t *Map) String() string        { return TypeString(t, nil) }
+func (t *Chan) String() string       { return TypeString(t, nil) }
+func (t *Named) String() string      { return TypeString(t, nil) }
+func (t *_TypeParam) String() string { return TypeString(t, nil) }
+func (t *instance) String() string   { return TypeString(t, nil) }
+func (t *bottom) String() string     { return TypeString(t, nil) }
+func (t *top) String() string        { return TypeString(t, nil) }
 
 // under returns the true expanded underlying type.
 // If it doesn't exist, the result is Typ[Invalid].
@@ -909,22 +909,11 @@ func asSlice(t Type) *Slice {
        return op
 }
 
-// TODO (rFindley) delete this on the dev.typeparams branch. This is only
-// exported in the prototype for legacy compatibility.
-func AsStruct(t Type) *Struct {
-       return asStruct(t)
-}
-
 func asStruct(t Type) *Struct {
        op, _ := optype(t).(*Struct)
        return op
 }
 
-// TODO(rFindley) delete this on the dev.typeparams branch (see ToStruct).
-func AsPointer(t Type) *Pointer {
-       return asPointer(t)
-}
-
 func asPointer(t Type) *Pointer {
        op, _ := optype(t).(*Pointer)
        return op
@@ -940,8 +929,8 @@ func asSignature(t Type) *Signature {
        return op
 }
 
-func asSum(t Type) *Sum {
-       op, _ := optype(t).(*Sum)
+func asSum(t Type) *_Sum {
+       op, _ := optype(t).(*_Sum)
        return op
 }
 
@@ -969,7 +958,7 @@ func asNamed(t Type) *Named {
        return e
 }
 
-func asTypeParam(t Type) *TypeParam {
-       u, _ := under(t).(*TypeParam)
+func asTypeParam(t Type) *_TypeParam {
+       u, _ := under(t).(*_TypeParam)
        return u
 }
index a0caded1606777e10bf746276cf485948296c98e..fe27f0f276c30e5127b2a0d61c1145b56b1105cf 100644 (file)
@@ -158,7 +158,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
                buf.WriteString("func")
                writeSignature(buf, t, qf, visited)
 
-       case *Sum:
+       case *_Sum:
                for i, t := range t.types {
                        if i > 0 {
                                buf.WriteString(", ")
@@ -279,7 +279,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
                        writeTParamList(buf, t.tparams, qf, visited)
                }
 
-       case *TypeParam:
+       case *_TypeParam:
                s := "?"
                if t.obj != nil {
                        s = t.obj.name
@@ -321,7 +321,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited
        for i, p := range list {
                // TODO(rFindley) support 'any' sugar here.
                var b Type = &emptyInterface
-               if t, _ := p.typ.(*TypeParam); t != nil && t.bound != nil {
+               if t, _ := p.typ.(*_TypeParam); t != nil && t.bound != nil {
                        b = t.bound
                }
                if i > 0 {
@@ -334,7 +334,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited
                }
                prev = b
 
-               if t, _ := p.typ.(*TypeParam); t != nil {
+               if t, _ := p.typ.(*_TypeParam); t != nil {
                        writeType(buf, t, qf, visited)
                } else {
                        buf.WriteString(p.name)
index 53c87f20d54a03f6b3747517f6b141a3e4c1542c..8f30a67a2f7ebf8cb84b4838d2be45dc57c05f94 100644 (file)
@@ -146,7 +146,7 @@ func (check *Checker) ordinaryType(pos positioner, typ Type) {
                                check.softErrorf(pos, _Todo, "interface contains type constraints (%s)", t.allTypes)
                                return
                        }
-                       if t.IsComparable() {
+                       if t._IsComparable() {
                                check.softErrorf(pos, _Todo, "interface is (or embeds) comparable")
                        }
                }
@@ -301,7 +301,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                                }
                                smap := makeSubstMap(recvTParams, list)
                                for i, tname := range sig.rparams {
-                                       bound := recvTParams[i].typ.(*TypeParam).bound
+                                       bound := recvTParams[i].typ.(*_TypeParam).bound
                                        // bound is (possibly) parameterized in the context of the
                                        // receiver type declaration. Substitute parameters for the
                                        // current context.
@@ -309,7 +309,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                                        //           (no bound == empty interface)
                                        if bound != nil {
                                                bound = check.subst(tname.pos, bound, smap)
-                                               tname.typ.(*TypeParam).bound = bound
+                                               tname.typ.(*_TypeParam).bound = bound
                                        }
                                }
                        }
@@ -333,7 +333,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
        recvList, _ := check.collectParams(scope, recvPar, recvTyp, false) // use rewritten receiver type, if any
        params, variadic := check.collectParams(scope, ftyp.Params, nil, true)
        results, _ := check.collectParams(scope, ftyp.Results, nil, false)
-       scope.Squash(func(obj, alt Object) {
+       scope.squash(func(obj, alt Object) {
                check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name())
                check.reportAltDecl(alt)
        })
@@ -823,7 +823,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
        }
 
        // type constraints
-       ityp.types = NewSum(check.collectTypeConstraints(iface.Pos(), types))
+       ityp.types = _NewSum(check.collectTypeConstraints(iface.Pos(), types))
 
        if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 {
                // empty interface
@@ -928,7 +928,7 @@ func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) {
                if etyp == nil {
                        if utyp != Typ[Invalid] {
                                var format string
-                               if _, ok := utyp.(*TypeParam); ok {
+                               if _, ok := utyp.(*_TypeParam); ok {
                                        format = "%s is a type parameter, not an interface"
                                } else {
                                        format = "%s is not an interface"
@@ -987,7 +987,7 @@ func intersect(x, y Type) (r Type) {
        if rtypes == nil {
                return theBottom
        }
-       return NewSum(rtypes)
+       return _NewSum(rtypes)
 }
 
 func sortTypes(list []Type) {
index ab18febbdfaa965d7250c72da5e95bec5d83c540..fbcd64c4428393afd8f6629417739646a112d79f 100644 (file)
@@ -83,7 +83,7 @@ func (d *tparamsList) init(tparams []*TypeName) {
        }
        if debug {
                for i, tpar := range tparams {
-                       assert(i == tpar.typ.(*TypeParam).index)
+                       assert(i == tpar.typ.(*_TypeParam).index)
                }
        }
        d.tparams = tparams
@@ -131,7 +131,7 @@ func (u *unifier) join(i, j int) bool {
 // If typ is a type parameter of d, index returns the type parameter index.
 // Otherwise, the result is < 0.
 func (d *tparamsList) index(typ Type) int {
-       if t, ok := typ.(*TypeParam); ok {
+       if t, ok := typ.(*_TypeParam); ok {
                if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t {
                        return i
                }
@@ -335,7 +335,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool {
                                u.nify(x.results, y.results, p)
                }
 
-       case *Sum:
+       case *_Sum:
                // This should not happen with the current internal use of sum types.
                panic("type inference across sum types not implemented")
 
@@ -431,7 +431,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool {
                        }
                }
 
-       case *TypeParam:
+       case *_TypeParam:
                // Two type parameters (which are not part of the type parameters of the
                // enclosing type as those are handled in the beginning of this function)
                // are identical if they originate in the same declaration.