]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types: expose types.Info.Inferred with -tags=typeparams
authorRob Findley <rfindley@google.com>
Thu, 6 May 2021 03:03:22 +0000 (23:03 -0400)
committerRobert Findley <rfindley@google.com>
Fri, 7 May 2021 01:42:23 +0000 (01:42 +0000)
Our workaround to get and set types.Info._Inferred makes it harder to
experiment with the new APIs in x/tools.

Instead, just make a copy of the types.Info struct, so that the Inferred
field is accessible when the typeparams build tag is set.

This is a trivially safe change: the only change when not building with
-tags=typeparams is that types.Info._Inferred is removed, and accessing
inferred type information goes through an additional layer of
indirection.

For #46003

Change-Id: I38f2bbb2c80aed28be31d0fe762ccead970476ca
Reviewed-on: https://go-review.googlesource.com/c/go/+/317549
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>
src/go/types/api.go
src/go/types/api_notypeparams.go [new file with mode: 0644]
src/go/types/api_typeparams.go
src/go/types/api_typeparams_test.go
src/go/types/check.go
src/go/types/sanitize.go

index da23c8c52aa9739e9e09bd5b875ede929f33f2f4..ed62a785d6c9c12ba9021348c7dc150b821c92f2 100644 (file)
@@ -160,101 +160,7 @@ func srcimporter_setUsesCgo(conf *Config) {
        conf.go115UsesCgo = true
 }
 
-// Info holds result type information for a type-checked package.
-// Only the information for which a map is provided is collected.
-// If the package has type errors, the collected information may
-// be incomplete.
-type Info struct {
-       // Types maps expressions to their types, and for constant
-       // expressions, also their values. Invalid expressions are
-       // omitted.
-       //
-       // For (possibly parenthesized) identifiers denoting built-in
-       // functions, the recorded signatures are call-site specific:
-       // if the call result is not a constant, the recorded type is
-       // an argument-specific signature. Otherwise, the recorded type
-       // is invalid.
-       //
-       // The Types map does not record the type of every identifier,
-       // only those that appear where an arbitrary expression is
-       // permitted. For instance, the identifier f in a selector
-       // expression x.f is found only in the Selections map, the
-       // identifier z in a variable declaration 'var z int' is found
-       // only in the Defs map, and identifiers denoting packages in
-       // 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
-       // 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
-
-       // Defs maps identifiers to the objects they define (including
-       // package names, dots "." of dot-imports, and blank "_" identifiers).
-       // For identifiers that do not denote objects (e.g., the package name
-       // in package clauses, or symbolic variables t in t := x.(type) of
-       // type switch headers), the corresponding objects are nil.
-       //
-       // For an embedded field, Defs returns the field *Var it defines.
-       //
-       // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
-       Defs map[*ast.Ident]Object
-
-       // Uses maps identifiers to the objects they denote.
-       //
-       // For an embedded field, Uses returns the *TypeName it denotes.
-       //
-       // Invariant: Uses[id].Pos() != id.Pos()
-       Uses map[*ast.Ident]Object
-
-       // Implicits maps nodes to their implicitly declared objects, if any.
-       // The following node and object types may appear:
-       //
-       //     node               declared object
-       //
-       //     *ast.ImportSpec    *PkgName for imports without renames
-       //     *ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
-       //     *ast.Field         anonymous parameter *Var (incl. unnamed results)
-       //
-       Implicits map[ast.Node]Object
-
-       // Selections maps selector expressions (excluding qualified identifiers)
-       // to their corresponding selections.
-       Selections map[*ast.SelectorExpr]*Selection
-
-       // Scopes maps ast.Nodes to the scopes they define. Package scopes are not
-       // associated with a specific node but with all files belonging to a package.
-       // Thus, the package scope can be found in the type-checked Package object.
-       // Scopes nest, with the Universe scope being the outermost scope, enclosing
-       // the package scope, which contains (one or more) files scopes, which enclose
-       // function scopes which in turn enclose statement and function literal scopes.
-       // Note that even though package-level functions are declared in the package
-       // scope, the function scopes are embedded in the file scope of the file
-       // containing the function declaration.
-       //
-       // The following node types may appear in Scopes:
-       //
-       //     *ast.File
-       //     *ast.FuncType
-       //     *ast.BlockStmt
-       //     *ast.IfStmt
-       //     *ast.SwitchStmt
-       //     *ast.TypeSwitchStmt
-       //     *ast.CaseClause
-       //     *ast.CommClause
-       //     *ast.ForStmt
-       //     *ast.RangeStmt
-       //
-       Scopes map[ast.Node]*Scope
-
-       // InitOrder is the list of package-level initializers in the order in which
-       // they must be executed. Initializers referring to variables related by an
-       // initialization dependency appear in topological order, the others appear
-       // in source order. Variables without an initialization expression do not
-       // appear in this list.
-       InitOrder []*Initializer
-}
+// The Info struct is found in api_notypeparams.go and api_typeparams.go.
 
 // TypeOf returns the type of expression e, or nil if not found.
 // Precondition: the Types, Uses and Defs maps are populated.
diff --git a/src/go/types/api_notypeparams.go b/src/go/types/api_notypeparams.go
new file mode 100644 (file)
index 0000000..9f7cb7e
--- /dev/null
@@ -0,0 +1,104 @@
+// 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 !typeparams
+// +build !typeparams
+
+package types
+
+import "go/ast"
+
+// Info holds result type information for a type-checked package.
+// Only the information for which a map is provided is collected.
+// If the package has type errors, the collected information may
+// be incomplete.
+type Info struct {
+       // Types maps expressions to their types, and for constant
+       // expressions, also their values. Invalid expressions are
+       // omitted.
+       //
+       // For (possibly parenthesized) identifiers denoting built-in
+       // functions, the recorded signatures are call-site specific:
+       // if the call result is not a constant, the recorded type is
+       // an argument-specific signature. Otherwise, the recorded type
+       // is invalid.
+       //
+       // The Types map does not record the type of every identifier,
+       // only those that appear where an arbitrary expression is
+       // permitted. For instance, the identifier f in a selector
+       // expression x.f is found only in the Selections map, the
+       // identifier z in a variable declaration 'var z int' is found
+       // only in the Defs map, and identifiers denoting packages in
+       // qualified identifiers are collected in the Uses map.
+       Types map[ast.Expr]TypeAndValue
+
+       // Defs maps identifiers to the objects they define (including
+       // package names, dots "." of dot-imports, and blank "_" identifiers).
+       // For identifiers that do not denote objects (e.g., the package name
+       // in package clauses, or symbolic variables t in t := x.(type) of
+       // type switch headers), the corresponding objects are nil.
+       //
+       // For an embedded field, Defs returns the field *Var it defines.
+       //
+       // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
+       Defs map[*ast.Ident]Object
+
+       // Uses maps identifiers to the objects they denote.
+       //
+       // For an embedded field, Uses returns the *TypeName it denotes.
+       //
+       // Invariant: Uses[id].Pos() != id.Pos()
+       Uses map[*ast.Ident]Object
+
+       // Implicits maps nodes to their implicitly declared objects, if any.
+       // The following node and object types may appear:
+       //
+       //     node               declared object
+       //
+       //     *ast.ImportSpec    *PkgName for imports without renames
+       //     *ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
+       //     *ast.Field         anonymous parameter *Var (incl. unnamed results)
+       //
+       Implicits map[ast.Node]Object
+
+       // Selections maps selector expressions (excluding qualified identifiers)
+       // to their corresponding selections.
+       Selections map[*ast.SelectorExpr]*Selection
+
+       // Scopes maps ast.Nodes to the scopes they define. Package scopes are not
+       // associated with a specific node but with all files belonging to a package.
+       // Thus, the package scope can be found in the type-checked Package object.
+       // Scopes nest, with the Universe scope being the outermost scope, enclosing
+       // the package scope, which contains (one or more) files scopes, which enclose
+       // function scopes which in turn enclose statement and function literal scopes.
+       // Note that even though package-level functions are declared in the package
+       // scope, the function scopes are embedded in the file scope of the file
+       // containing the function declaration.
+       //
+       // The following node types may appear in Scopes:
+       //
+       //     *ast.File
+       //     *ast.FuncType
+       //     *ast.BlockStmt
+       //     *ast.IfStmt
+       //     *ast.SwitchStmt
+       //     *ast.TypeSwitchStmt
+       //     *ast.CaseClause
+       //     *ast.CommClause
+       //     *ast.ForStmt
+       //     *ast.RangeStmt
+       //
+       Scopes map[ast.Node]*Scope
+
+       // InitOrder is the list of package-level initializers in the order in which
+       // they must be executed. Initializers referring to variables related by an
+       // initialization dependency appear in topological order, the others appear
+       // in source order. Variables without an initialization expression do not
+       // appear in this list.
+       InitOrder []*Initializer
+}
+
+func getInferred(info *Info) map[ast.Expr]_Inferred {
+       return nil
+}
index 639bc3b3bfc56dca0dd503dcf216c6c8f3c88df1..ed744c4dba6a151623c283bbb396f4d9933ad555 100644 (file)
@@ -17,14 +17,6 @@ type (
        TypeParam = _TypeParam
 )
 
-func GetInferred(info *Info) map[ast.Expr]Inferred {
-       return info._Inferred
-}
-
-func SetInferred(info *Info, inferred map[ast.Expr]Inferred) {
-       info._Inferred = inferred
-}
-
 func NewSum(types []Type) Type { return _NewSum(types) }
 
 func (s *Signature) TParams() []*TypeName           { return s._TParams() }
@@ -37,3 +29,25 @@ func (t *Interface) IsConstraint() bool { return t._IsConstraint() }
 func (t *Named) TParams() []*TypeName { return t._TParams() }
 func (t *Named) TArgs() []Type        { return t._TArgs() }
 func (t *Named) SetTArgs(args []Type) { t._SetTArgs(args) }
+
+// Info is documented in api_notypeparams.go.
+type Info struct {
+       Types map[ast.Expr]TypeAndValue
+
+       // 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
+
+       Defs       map[*ast.Ident]Object
+       Uses       map[*ast.Ident]Object
+       Implicits  map[ast.Node]Object
+       Selections map[*ast.SelectorExpr]*Selection
+       Scopes     map[ast.Node]*Scope
+       InitOrder  []*Initializer
+}
+
+func getInferred(info *Info) map[ast.Expr]_Inferred {
+       return info.Inferred
+}
index e6cccf8691a8016a7519e38118b86bcd9893d5fc..15c9bf09f9dfccc8910369422b1218f341535621 100644 (file)
@@ -88,7 +88,7 @@ func TestInferredInfo(t *testing.T) {
 
        for _, test := range tests {
                info := Info{}
-               SetInferred(&info, make(map[ast.Expr]Inferred))
+               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)
@@ -98,7 +98,7 @@ func TestInferredInfo(t *testing.T) {
                // look for inferred type arguments and signature
                var targs []Type
                var sig *Signature
-               for call, inf := range GetInferred(&info) {
+               for call, inf := range info.Inferred {
                        var fun ast.Expr
                        switch x := call.(type) {
                        case *ast.CallExpr:
index 1f64d3e3c3a6edb9acd4ddfc61caddc39b163342..25ea4906be35f52f38909b1d458c5416be8c2b0d 100644 (file)
@@ -411,7 +411,7 @@ 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 {
+       if m := getInferred(check.Info); m != nil {
                m[call] = _Inferred{targs, sig}
        }
 }
index b905972d367e660d46be14eed56e242ac192469d..5970ab38c712dacd6df3b22e770a14ed5e0c48b4 100644 (file)
@@ -24,7 +24,8 @@ func sanitizeInfo(info *Info) {
                }
        }
 
-       for e, inf := range info._Inferred {
+       inferred := getInferred(info)
+       for e, inf := range inferred {
                changed := false
                for i, targ := range inf.Targs {
                        if typ := s.typ(targ); typ != targ {
@@ -37,7 +38,7 @@ func sanitizeInfo(info *Info) {
                        changed = true
                }
                if changed {
-                       info._Inferred[e] = inf
+                       inferred[e] = inf
                }
        }