mirror of
https://github.com/golang/go.git
synced 2025-05-28 10:51:22 +00:00
go/types, types2: move exported predicates into separate file
This allows those functions to be generated for go/types. Also, change the generator's renameIdent mechanism so that it can rename multiple identifiers in one pass through the AST instead of requiring multiple passes. No type-checker functionality changes. Change-Id: Ic78d899c6004b6a0692a95902fdc13f8ffb47824 Reviewed-on: https://go-review.googlesource.com/c/go/+/542757 Run-TryBot: Robert Griesemer <gri@google.com> Reviewed-by: Robert Griesemer <gri@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> Auto-Submit: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
a95c5d37f2
commit
e62bf150cc
@ -460,80 +460,3 @@ func (conf *Config) Check(path string, files []*syntax.File, info *Info) (*Packa
|
||||
pkg := NewPackage(path, "")
|
||||
return pkg, NewChecker(conf, pkg, info).Files(files)
|
||||
}
|
||||
|
||||
// AssertableTo reports whether a value of type V can be asserted to have type T.
|
||||
//
|
||||
// The behavior of AssertableTo is unspecified in three cases:
|
||||
// - if T is Typ[Invalid]
|
||||
// - if V is a generalized interface; i.e., an interface that may only be used
|
||||
// as a type constraint in Go code
|
||||
// - if T is an uninstantiated generic type
|
||||
func AssertableTo(V *Interface, T Type) bool {
|
||||
// Checker.newAssertableTo suppresses errors for invalid types, so we need special
|
||||
// handling here.
|
||||
if !isValid(T.Underlying()) {
|
||||
return false
|
||||
}
|
||||
return (*Checker)(nil).newAssertableTo(nopos, V, T, nil)
|
||||
}
|
||||
|
||||
// AssignableTo reports whether a value of type V is assignable to a variable
|
||||
// of type T.
|
||||
//
|
||||
// The behavior of AssignableTo is unspecified if V or T is Typ[Invalid] or an
|
||||
// uninstantiated generic type.
|
||||
func AssignableTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x
|
||||
return ok
|
||||
}
|
||||
|
||||
// ConvertibleTo reports whether a value of type V is convertible to a value of
|
||||
// type T.
|
||||
//
|
||||
// The behavior of ConvertibleTo is unspecified if V or T is Typ[Invalid] or an
|
||||
// uninstantiated generic type.
|
||||
func ConvertibleTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
|
||||
}
|
||||
|
||||
// Implements reports whether type V implements interface T.
|
||||
//
|
||||
// The behavior of Implements is unspecified if V is Typ[Invalid] or an uninstantiated
|
||||
// generic type.
|
||||
func Implements(V Type, T *Interface) bool {
|
||||
if T.Empty() {
|
||||
// All types (even Typ[Invalid]) implement the empty interface.
|
||||
return true
|
||||
}
|
||||
// Checker.implements suppresses errors for invalid types, so we need special
|
||||
// handling here.
|
||||
if !isValid(V.Underlying()) {
|
||||
return false
|
||||
}
|
||||
return (*Checker)(nil).implements(nopos, V, T, false, nil)
|
||||
}
|
||||
|
||||
// Satisfies reports whether type V satisfies the constraint T.
|
||||
//
|
||||
// The behavior of Satisfies is unspecified if V is Typ[Invalid] or an uninstantiated
|
||||
// generic type.
|
||||
func Satisfies(V Type, T *Interface) bool {
|
||||
return (*Checker)(nil).implements(nopos, V, T, true, nil)
|
||||
}
|
||||
|
||||
// Identical reports whether x and y are identical types.
|
||||
// Receivers of Signature types are ignored.
|
||||
func Identical(x, y Type) bool {
|
||||
var c comparer
|
||||
return c.identical(x, y, nil)
|
||||
}
|
||||
|
||||
// IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored.
|
||||
// Receivers of Signature types are ignored.
|
||||
func IdenticalIgnoreTags(x, y Type) bool {
|
||||
var c comparer
|
||||
c.ignoreTags = true
|
||||
return c.identical(x, y, nil)
|
||||
}
|
||||
|
84
src/cmd/compile/internal/types2/api_predicates.go
Normal file
84
src/cmd/compile/internal/types2/api_predicates.go
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright 2023 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.
|
||||
|
||||
// This file implements exported type predicates.
|
||||
|
||||
package types2
|
||||
|
||||
// AssertableTo reports whether a value of type V can be asserted to have type T.
|
||||
//
|
||||
// The behavior of AssertableTo is unspecified in three cases:
|
||||
// - if T is Typ[Invalid]
|
||||
// - if V is a generalized interface; i.e., an interface that may only be used
|
||||
// as a type constraint in Go code
|
||||
// - if T is an uninstantiated generic type
|
||||
func AssertableTo(V *Interface, T Type) bool {
|
||||
// Checker.newAssertableTo suppresses errors for invalid types, so we need special
|
||||
// handling here.
|
||||
if !isValid(T.Underlying()) {
|
||||
return false
|
||||
}
|
||||
return (*Checker)(nil).newAssertableTo(nopos, V, T, nil)
|
||||
}
|
||||
|
||||
// AssignableTo reports whether a value of type V is assignable to a variable
|
||||
// of type T.
|
||||
//
|
||||
// The behavior of AssignableTo is unspecified if V or T is Typ[Invalid] or an
|
||||
// uninstantiated generic type.
|
||||
func AssignableTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x
|
||||
return ok
|
||||
}
|
||||
|
||||
// ConvertibleTo reports whether a value of type V is convertible to a value of
|
||||
// type T.
|
||||
//
|
||||
// The behavior of ConvertibleTo is unspecified if V or T is Typ[Invalid] or an
|
||||
// uninstantiated generic type.
|
||||
func ConvertibleTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
|
||||
}
|
||||
|
||||
// Implements reports whether type V implements interface T.
|
||||
//
|
||||
// The behavior of Implements is unspecified if V is Typ[Invalid] or an uninstantiated
|
||||
// generic type.
|
||||
func Implements(V Type, T *Interface) bool {
|
||||
if T.Empty() {
|
||||
// All types (even Typ[Invalid]) implement the empty interface.
|
||||
return true
|
||||
}
|
||||
// Checker.implements suppresses errors for invalid types, so we need special
|
||||
// handling here.
|
||||
if !isValid(V.Underlying()) {
|
||||
return false
|
||||
}
|
||||
return (*Checker)(nil).implements(nopos, V, T, false, nil)
|
||||
}
|
||||
|
||||
// Satisfies reports whether type V satisfies the constraint T.
|
||||
//
|
||||
// The behavior of Satisfies is unspecified if V is Typ[Invalid] or an uninstantiated
|
||||
// generic type.
|
||||
func Satisfies(V Type, T *Interface) bool {
|
||||
return (*Checker)(nil).implements(nopos, V, T, true, nil)
|
||||
}
|
||||
|
||||
// Identical reports whether x and y are identical types.
|
||||
// Receivers of [Signature] types are ignored.
|
||||
func Identical(x, y Type) bool {
|
||||
var c comparer
|
||||
return c.identical(x, y, nil)
|
||||
}
|
||||
|
||||
// IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored.
|
||||
// Receivers of [Signature] types are ignored.
|
||||
func IdenticalIgnoreTags(x, y Type) bool {
|
||||
var c comparer
|
||||
c.ignoreTags = true
|
||||
return c.identical(x, y, nil)
|
||||
}
|
@ -448,80 +448,3 @@ func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, i
|
||||
pkg := NewPackage(path, "")
|
||||
return pkg, NewChecker(conf, fset, pkg, info).Files(files)
|
||||
}
|
||||
|
||||
// AssertableTo reports whether a value of type V can be asserted to have type T.
|
||||
//
|
||||
// The behavior of AssertableTo is unspecified in three cases:
|
||||
// - if T is Typ[Invalid]
|
||||
// - if V is a generalized interface; i.e., an interface that may only be used
|
||||
// as a type constraint in Go code
|
||||
// - if T is an uninstantiated generic type
|
||||
func AssertableTo(V *Interface, T Type) bool {
|
||||
// Checker.newAssertableTo suppresses errors for invalid types, so we need special
|
||||
// handling here.
|
||||
if !isValid(T.Underlying()) {
|
||||
return false
|
||||
}
|
||||
return (*Checker)(nil).newAssertableTo(nopos, V, T, nil)
|
||||
}
|
||||
|
||||
// AssignableTo reports whether a value of type V is assignable to a variable
|
||||
// of type T.
|
||||
//
|
||||
// The behavior of AssignableTo is unspecified if V or T is Typ[Invalid] or an
|
||||
// uninstantiated generic type.
|
||||
func AssignableTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x
|
||||
return ok
|
||||
}
|
||||
|
||||
// ConvertibleTo reports whether a value of type V is convertible to a value of
|
||||
// type T.
|
||||
//
|
||||
// The behavior of ConvertibleTo is unspecified if V or T is Typ[Invalid] or an
|
||||
// uninstantiated generic type.
|
||||
func ConvertibleTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
|
||||
}
|
||||
|
||||
// Implements reports whether type V implements interface T.
|
||||
//
|
||||
// The behavior of Implements is unspecified if V is Typ[Invalid] or an uninstantiated
|
||||
// generic type.
|
||||
func Implements(V Type, T *Interface) bool {
|
||||
if T.Empty() {
|
||||
// All types (even Typ[Invalid]) implement the empty interface.
|
||||
return true
|
||||
}
|
||||
// Checker.implements suppresses errors for invalid types, so we need special
|
||||
// handling here.
|
||||
if !isValid(V.Underlying()) {
|
||||
return false
|
||||
}
|
||||
return (*Checker)(nil).implements(0, V, T, false, nil)
|
||||
}
|
||||
|
||||
// Satisfies reports whether type V satisfies the constraint T.
|
||||
//
|
||||
// The behavior of Satisfies is unspecified if V is Typ[Invalid] or an uninstantiated
|
||||
// generic type.
|
||||
func Satisfies(V Type, T *Interface) bool {
|
||||
return (*Checker)(nil).implements(0, V, T, true, nil)
|
||||
}
|
||||
|
||||
// Identical reports whether x and y are identical types.
|
||||
// Receivers of [Signature] types are ignored.
|
||||
func Identical(x, y Type) bool {
|
||||
var c comparer
|
||||
return c.identical(x, y, nil)
|
||||
}
|
||||
|
||||
// IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored.
|
||||
// Receivers of [Signature] types are ignored.
|
||||
func IdenticalIgnoreTags(x, y Type) bool {
|
||||
var c comparer
|
||||
c.ignoreTags = true
|
||||
return c.identical(x, y, nil)
|
||||
}
|
||||
|
86
src/go/types/api_predicates.go
Normal file
86
src/go/types/api_predicates.go
Normal file
@ -0,0 +1,86 @@
|
||||
// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
|
||||
|
||||
// Copyright 2023 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.
|
||||
|
||||
// This file implements exported type predicates.
|
||||
|
||||
package types
|
||||
|
||||
// AssertableTo reports whether a value of type V can be asserted to have type T.
|
||||
//
|
||||
// The behavior of AssertableTo is unspecified in three cases:
|
||||
// - if T is Typ[Invalid]
|
||||
// - if V is a generalized interface; i.e., an interface that may only be used
|
||||
// as a type constraint in Go code
|
||||
// - if T is an uninstantiated generic type
|
||||
func AssertableTo(V *Interface, T Type) bool {
|
||||
// Checker.newAssertableTo suppresses errors for invalid types, so we need special
|
||||
// handling here.
|
||||
if !isValid(T.Underlying()) {
|
||||
return false
|
||||
}
|
||||
return (*Checker)(nil).newAssertableTo(nopos, V, T, nil)
|
||||
}
|
||||
|
||||
// AssignableTo reports whether a value of type V is assignable to a variable
|
||||
// of type T.
|
||||
//
|
||||
// The behavior of AssignableTo is unspecified if V or T is Typ[Invalid] or an
|
||||
// uninstantiated generic type.
|
||||
func AssignableTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x
|
||||
return ok
|
||||
}
|
||||
|
||||
// ConvertibleTo reports whether a value of type V is convertible to a value of
|
||||
// type T.
|
||||
//
|
||||
// The behavior of ConvertibleTo is unspecified if V or T is Typ[Invalid] or an
|
||||
// uninstantiated generic type.
|
||||
func ConvertibleTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
|
||||
}
|
||||
|
||||
// Implements reports whether type V implements interface T.
|
||||
//
|
||||
// The behavior of Implements is unspecified if V is Typ[Invalid] or an uninstantiated
|
||||
// generic type.
|
||||
func Implements(V Type, T *Interface) bool {
|
||||
if T.Empty() {
|
||||
// All types (even Typ[Invalid]) implement the empty interface.
|
||||
return true
|
||||
}
|
||||
// Checker.implements suppresses errors for invalid types, so we need special
|
||||
// handling here.
|
||||
if !isValid(V.Underlying()) {
|
||||
return false
|
||||
}
|
||||
return (*Checker)(nil).implements(nopos, V, T, false, nil)
|
||||
}
|
||||
|
||||
// Satisfies reports whether type V satisfies the constraint T.
|
||||
//
|
||||
// The behavior of Satisfies is unspecified if V is Typ[Invalid] or an uninstantiated
|
||||
// generic type.
|
||||
func Satisfies(V Type, T *Interface) bool {
|
||||
return (*Checker)(nil).implements(nopos, V, T, true, nil)
|
||||
}
|
||||
|
||||
// Identical reports whether x and y are identical types.
|
||||
// Receivers of [Signature] types are ignored.
|
||||
func Identical(x, y Type) bool {
|
||||
var c comparer
|
||||
return c.identical(x, y, nil)
|
||||
}
|
||||
|
||||
// IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored.
|
||||
// Receivers of [Signature] types are ignored.
|
||||
func IdenticalIgnoreTags(x, y Type) bool {
|
||||
var c comparer
|
||||
c.ignoreTags = true
|
||||
return c.identical(x, y, nil)
|
||||
}
|
@ -95,16 +95,17 @@ func generate(t *testing.T, filename string, write bool) {
|
||||
type action func(in *ast.File)
|
||||
|
||||
var filemap = map[string]action{
|
||||
"alias.go": nil,
|
||||
"array.go": nil,
|
||||
"basic.go": nil,
|
||||
"chan.go": nil,
|
||||
"const.go": func(f *ast.File) { fixTokenPos(f) },
|
||||
"context.go": nil,
|
||||
"context_test.go": nil,
|
||||
"gccgosizes.go": nil,
|
||||
"gcsizes.go": func(f *ast.File) { renameIdent(f, "IsSyncAtomicAlign64", "_IsSyncAtomicAlign64") },
|
||||
"hilbert_test.go": func(f *ast.File) { renameImportPath(f, `"cmd/compile/internal/types2"`, `"go/types"`) },
|
||||
"alias.go": nil,
|
||||
"array.go": nil,
|
||||
"api_predicates.go": nil,
|
||||
"basic.go": nil,
|
||||
"chan.go": nil,
|
||||
"const.go": func(f *ast.File) { fixTokenPos(f) },
|
||||
"context.go": nil,
|
||||
"context_test.go": nil,
|
||||
"gccgosizes.go": nil,
|
||||
"gcsizes.go": func(f *ast.File) { renameIdents(f, "IsSyncAtomicAlign64->_IsSyncAtomicAlign64") },
|
||||
"hilbert_test.go": func(f *ast.File) { renameImportPath(f, `"cmd/compile/internal/types2"`, `"go/types"`) },
|
||||
"infer.go": func(f *ast.File) {
|
||||
fixTokenPos(f)
|
||||
fixInferSig(f)
|
||||
@ -116,7 +117,7 @@ var filemap = map[string]action{
|
||||
"main_test.go": nil,
|
||||
"map.go": nil,
|
||||
"named.go": func(f *ast.File) { fixTokenPos(f); fixTraceSel(f) },
|
||||
"object.go": func(f *ast.File) { fixTokenPos(f); renameIdent(f, "NewTypeNameLazy", "_NewTypeNameLazy") },
|
||||
"object.go": func(f *ast.File) { fixTokenPos(f); renameIdents(f, "NewTypeNameLazy->_NewTypeNameLazy") },
|
||||
"object_test.go": func(f *ast.File) { renameImportPath(f, `"cmd/compile/internal/types2"`, `"go/types"`) },
|
||||
"objset.go": nil,
|
||||
"package.go": nil,
|
||||
@ -124,11 +125,10 @@ var filemap = map[string]action{
|
||||
"predicates.go": nil,
|
||||
"scope.go": func(f *ast.File) {
|
||||
fixTokenPos(f)
|
||||
renameIdent(f, "Squash", "squash")
|
||||
renameIdent(f, "InsertLazy", "_InsertLazy")
|
||||
renameIdents(f, "Squash->squash", "InsertLazy->_InsertLazy")
|
||||
},
|
||||
"selection.go": nil,
|
||||
"sizes.go": func(f *ast.File) { renameIdent(f, "IsSyncAtomicAlign64", "_IsSyncAtomicAlign64") },
|
||||
"sizes.go": func(f *ast.File) { renameIdents(f, "IsSyncAtomicAlign64->_IsSyncAtomicAlign64") },
|
||||
"slice.go": nil,
|
||||
"subst.go": func(f *ast.File) { fixTokenPos(f); fixTraceSel(f) },
|
||||
"termlist.go": nil,
|
||||
@ -148,14 +148,24 @@ var filemap = map[string]action{
|
||||
// TODO(gri) We should be able to make these rewriters more configurable/composable.
|
||||
// For now this is a good starting point.
|
||||
|
||||
// renameIdent renames an identifier.
|
||||
// Note: This doesn't change the use of the identifier in comments.
|
||||
func renameIdent(f *ast.File, from, to string) {
|
||||
// renameIdent renames identifiers: each renames entry is of the form from->to.
|
||||
// Note: This doesn't change the use of the identifiers in comments.
|
||||
func renameIdents(f *ast.File, renames ...string) {
|
||||
var list [][]string
|
||||
for _, r := range renames {
|
||||
s := strings.Split(r, "->")
|
||||
if len(s) != 2 {
|
||||
panic("invalid rename entry: " + r)
|
||||
}
|
||||
list = append(list, s)
|
||||
}
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
switch n := n.(type) {
|
||||
case *ast.Ident:
|
||||
if n.Name == from {
|
||||
n.Name = to
|
||||
for _, r := range list {
|
||||
if n.Name == r[0] {
|
||||
n.Name = r[1]
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user