mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
go/types: expose types.Info.Inferred with -tags=typeparams
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>
This commit is contained in:
parent
4dbad79510
commit
a11a1711b0
6 changed files with 133 additions and 108 deletions
|
|
@ -160,101 +160,7 @@ func srcimporter_setUsesCgo(conf *Config) {
|
||||||
conf.go115UsesCgo = true
|
conf.go115UsesCgo = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info holds result type information for a type-checked package.
|
// The Info struct is found in api_notypeparams.go and api_typeparams.go.
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// TypeOf returns the type of expression e, or nil if not found.
|
// TypeOf returns the type of expression e, or nil if not found.
|
||||||
// Precondition: the Types, Uses and Defs maps are populated.
|
// Precondition: the Types, Uses and Defs maps are populated.
|
||||||
|
|
|
||||||
104
src/go/types/api_notypeparams.go
Normal file
104
src/go/types/api_notypeparams.go
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -17,14 +17,6 @@ type (
|
||||||
TypeParam = _TypeParam
|
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 NewSum(types []Type) Type { return _NewSum(types) }
|
||||||
|
|
||||||
func (s *Signature) TParams() []*TypeName { return s._TParams() }
|
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) TParams() []*TypeName { return t._TParams() }
|
||||||
func (t *Named) TArgs() []Type { return t._TArgs() }
|
func (t *Named) TArgs() []Type { return t._TArgs() }
|
||||||
func (t *Named) SetTArgs(args []Type) { t._SetTArgs(args) }
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ func TestInferredInfo(t *testing.T) {
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
info := Info{}
|
info := Info{}
|
||||||
SetInferred(&info, make(map[ast.Expr]Inferred))
|
info.Inferred = make(map[ast.Expr]Inferred)
|
||||||
name, err := mayTypecheck(t, "InferredInfo", test.src, &info)
|
name, err := mayTypecheck(t, "InferredInfo", test.src, &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("package %s: %v", name, err)
|
t.Errorf("package %s: %v", name, err)
|
||||||
|
|
@ -98,7 +98,7 @@ func TestInferredInfo(t *testing.T) {
|
||||||
// look for inferred type arguments and signature
|
// look for inferred type arguments and signature
|
||||||
var targs []Type
|
var targs []Type
|
||||||
var sig *Signature
|
var sig *Signature
|
||||||
for call, inf := range GetInferred(&info) {
|
for call, inf := range info.Inferred {
|
||||||
var fun ast.Expr
|
var fun ast.Expr
|
||||||
switch x := call.(type) {
|
switch x := call.(type) {
|
||||||
case *ast.CallExpr:
|
case *ast.CallExpr:
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature) {
|
||||||
assert(call != nil)
|
assert(call != nil)
|
||||||
assert(sig != nil)
|
assert(sig != nil)
|
||||||
if m := check._Inferred; m != nil {
|
if m := getInferred(check.Info); m != nil {
|
||||||
m[call] = _Inferred{targs, sig}
|
m[call] = _Inferred{targs, sig}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ func sanitizeInfo(info *Info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for e, inf := range info._Inferred {
|
inferred := getInferred(info)
|
||||||
|
for e, inf := range inferred {
|
||||||
changed := false
|
changed := false
|
||||||
for i, targ := range inf.Targs {
|
for i, targ := range inf.Targs {
|
||||||
if typ := s.typ(targ); typ != targ {
|
if typ := s.typ(targ); typ != targ {
|
||||||
|
|
@ -37,7 +38,7 @@ func sanitizeInfo(info *Info) {
|
||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
if changed {
|
if changed {
|
||||||
info._Inferred[e] = inf
|
inferred[e] = inf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue