go/types, types2: factor out typechecker-specific code from recording.go

With this CL, the go/types and types2 recording.go files are
mostly identical except for the use of different syntax trees.
Preparation for generating go/types/recording.go from types2
sources.

Change-Id: Iea85f8554ee04f1e1f7da63f8019725ac8f6caf5
Reviewed-on: https://go-review.googlesource.com/c/go/+/602117
Reviewed-by: Tim King <taking@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Robert Griesemer 2024-07-31 09:59:28 -07:00 committed by Gopher Robot
parent c5de950766
commit 1b6bb779ef
4 changed files with 117 additions and 92 deletions

View File

@ -514,3 +514,80 @@ func (check *Checker) cleanup() {
}
check.cleaners = nil
}
// types2-specific support for recording type information in the syntax tree.
func (check *Checker) recordTypeAndValueInSyntax(x syntax.Expr, mode operandMode, typ Type, val constant.Value) {
if check.StoreTypesInSyntax {
tv := TypeAndValue{mode, typ, val}
stv := syntax.TypeAndValue{Type: typ, Value: val}
if tv.IsVoid() {
stv.SetIsVoid()
}
if tv.IsType() {
stv.SetIsType()
}
if tv.IsBuiltin() {
stv.SetIsBuiltin()
}
if tv.IsValue() {
stv.SetIsValue()
}
if tv.IsNil() {
stv.SetIsNil()
}
if tv.Addressable() {
stv.SetAddressable()
}
if tv.Assignable() {
stv.SetAssignable()
}
if tv.HasOk() {
stv.SetHasOk()
}
x.SetTypeInfo(stv)
}
}
// types2-specific support for recording type information in the syntax tree.
func (check *Checker) recordCommaOkTypesInSyntax(x syntax.Expr, t0, t1 Type) {
if check.StoreTypesInSyntax {
// Note: this loop is duplicated because the type of tv is different.
// Above it is types2.TypeAndValue, here it is syntax.TypeAndValue.
for {
tv := x.GetTypeInfo()
assert(tv.Type != nil) // should have been recorded already
pos := x.Pos()
tv.Type = NewTuple(
NewVar(pos, check.pkg, "", t0),
NewVar(pos, check.pkg, "", t1),
)
x.SetTypeInfo(tv)
p, _ := x.(*syntax.ParenExpr)
if p == nil {
break
}
x = p.X
}
}
}
// instantiatedIdent determines the identifier of the type instantiated in expr.
// Helper function for recordInstance in recording.go.
func instantiatedIdent(expr syntax.Expr) *syntax.Name {
var selOrIdent syntax.Expr
switch e := expr.(type) {
case *syntax.IndexExpr:
selOrIdent = e.X
case *syntax.SelectorExpr, *syntax.Name:
selOrIdent = e
}
switch x := selOrIdent.(type) {
case *syntax.Name:
return x
case *syntax.SelectorExpr:
return x.Sel
}
// extra debugging of go.dev/issue/63933
panic(sprintf(nil, true, "instantiated ident not found; please report: %s", expr))
}

View File

@ -68,35 +68,7 @@ func (check *Checker) recordTypeAndValue(x syntax.Expr, mode operandMode, typ Ty
if m := check.Types; m != nil {
m[x] = TypeAndValue{mode, typ, val}
}
if check.StoreTypesInSyntax {
tv := TypeAndValue{mode, typ, val}
stv := syntax.TypeAndValue{Type: typ, Value: val}
if tv.IsVoid() {
stv.SetIsVoid()
}
if tv.IsType() {
stv.SetIsType()
}
if tv.IsBuiltin() {
stv.SetIsBuiltin()
}
if tv.IsValue() {
stv.SetIsValue()
}
if tv.IsNil() {
stv.SetIsNil()
}
if tv.Addressable() {
stv.SetAddressable()
}
if tv.Assignable() {
stv.SetAssignable()
}
if tv.HasOk() {
stv.SetHasOk()
}
x.SetTypeInfo(stv)
}
check.recordTypeAndValueInSyntax(x, mode, typ, val)
}
func (check *Checker) recordBuiltinType(f syntax.Expr, sig *Signature) {
@ -145,25 +117,7 @@ func (check *Checker) recordCommaOkTypes(x syntax.Expr, a []*operand) {
x = p.X
}
}
if check.StoreTypesInSyntax {
// Note: this loop is duplicated because the type of tv is different.
// Above it is types2.TypeAndValue, here it is syntax.TypeAndValue.
for {
tv := x.GetTypeInfo()
assert(tv.Type != nil) // should have been recorded already
pos := x.Pos()
tv.Type = NewTuple(
NewVar(pos, check.pkg, "", t0),
NewVar(pos, check.pkg, "", t1),
)
x.SetTypeInfo(tv)
p, _ := x.(*syntax.ParenExpr)
if p == nil {
break
}
x = p.X
}
}
check.recordCommaOkTypesInSyntax(x, t0, t1)
}
// recordInstance records instantiation information into check.Info, if the
@ -181,23 +135,6 @@ func (check *Checker) recordInstance(expr syntax.Expr, targs []Type, typ Type) {
}
}
func instantiatedIdent(expr syntax.Expr) *syntax.Name {
var selOrIdent syntax.Expr
switch e := expr.(type) {
case *syntax.IndexExpr:
selOrIdent = e.X
case *syntax.SelectorExpr, *syntax.Name:
selOrIdent = e
}
switch x := selOrIdent.(type) {
case *syntax.Name:
return x
case *syntax.SelectorExpr:
return x.Sel
}
panic("instantiated ident not found")
}
func (check *Checker) recordDef(id *syntax.Name, obj Object) {
assert(id != nil)
if m := check.Defs; m != nil {

View File

@ -535,3 +535,38 @@ func (check *Checker) cleanup() {
}
check.cleaners = nil
}
// go/types doesn't support recording of types directly in the AST.
// dummy function to match types2 code.
func (check *Checker) recordTypeAndValueInSyntax(x ast.Expr, mode operandMode, typ Type, val constant.Value) {
// nothing to do
}
// go/types doesn't support recording of types directly in the AST.
// dummy function to match types2 code.
func (check *Checker) recordCommaOkTypesInSyntax(x ast.Expr, t0, t1 Type) {
// nothing to do
}
// instantiatedIdent determines the identifier of the type instantiated in expr.
// Helper function for recordInstance in recording.go.
func instantiatedIdent(expr ast.Expr) *ast.Ident {
var selOrIdent ast.Expr
switch e := expr.(type) {
case *ast.IndexExpr:
selOrIdent = e.X
case *ast.IndexListExpr: // only exists in go/ast, not syntax
selOrIdent = e.X
case *ast.SelectorExpr, *ast.Ident:
selOrIdent = e
}
switch x := selOrIdent.(type) {
case *ast.Ident:
return x
case *ast.SelectorExpr:
return x.Sel
}
// extra debugging of go.dev/issue/63933
panic(sprintf(nil, nil, true, "instantiated ident not found; please report: %s", expr))
}

View File

@ -10,8 +10,6 @@ package types
import (
"go/ast"
"go/constant"
"go/token"
"strings"
)
func (check *Checker) record(x *operand) {
@ -42,7 +40,7 @@ func (check *Checker) record(x *operand) {
}
func (check *Checker) recordUntyped() {
if !debug && check.Types == nil {
if !debug && !check.recordTypes() {
return // nothing to do
}
@ -70,6 +68,7 @@ func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type,
if m := check.Types; m != nil {
m[x] = TypeAndValue{mode, typ, val}
}
check.recordTypeAndValueInSyntax(x, mode, typ, val)
}
func (check *Checker) recordBuiltinType(f ast.Expr, sig *Signature) {
@ -118,6 +117,7 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a []*operand) {
x = p.X
}
}
check.recordCommaOkTypesInSyntax(x, t0, t1)
}
// recordInstance records instantiation information into check.Info, if the
@ -135,30 +135,6 @@ func (check *Checker) recordInstance(expr ast.Expr, targs []Type, typ Type) {
}
}
func instantiatedIdent(expr ast.Expr) *ast.Ident {
var selOrIdent ast.Expr
switch e := expr.(type) {
case *ast.IndexExpr:
selOrIdent = e.X
case *ast.IndexListExpr:
selOrIdent = e.X
case *ast.SelectorExpr, *ast.Ident:
selOrIdent = e
}
switch x := selOrIdent.(type) {
case *ast.Ident:
return x
case *ast.SelectorExpr:
return x.Sel
}
// extra debugging of #63933
var buf strings.Builder
buf.WriteString("instantiated ident not found; please report: ")
ast.Fprint(&buf, token.NewFileSet(), expr, ast.NotNilFilter)
panic(buf.String())
}
func (check *Checker) recordDef(id *ast.Ident, obj Object) {
assert(id != nil)
if m := check.Defs; m != nil {