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>
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)
-}
--- /dev/null
+// 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)
+}
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)
-}
--- /dev/null
+// 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)
+}
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)
"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,
"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,
// 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
}