mirror of https://github.com/golang/go.git
go/types: implement specific converter methods for *instance types
This is fixing a known issue (see below) and many unknown issues: An *instance type may legally represent any kind of type after instantiation. Given the declaration: type T(type P) P T(int) is now a valid constant type, and T([]int) is a valid slice type. Also, fixed the implementation of isTyped/isUntyped which caused types to expand prematurely. Change-Id: Ic71c7252e3b066b0f97c2f1892cf20b2c4c2ef98 Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/723717 Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
37801e2c49
commit
4843595d7f
|
|
@ -444,7 +444,7 @@ func TestDefsInfo(t *testing.T) {
|
|||
|
||||
// generic types must be sanitized
|
||||
// (need to use sufficiently nested types to provoke unexpanded types)
|
||||
// TODO(gri) add analogous test for constants, once T(int) is accepted as constant type
|
||||
{`package g0; type t(type P) P; const x = (t(int))(42)`, `x`, `const g0.x g0.t(int)`},
|
||||
{`package g1; type t(type P) P; var x = (t(int))(42)`, `x`, `var g1.x g1.t(int)`},
|
||||
{`package g2; type t(type P) P; type x struct{ f t(int) }`, `x`, `type g2.x struct{f g2.t(int)}`},
|
||||
{`package g3; type t(type P) P; func f(x struct{ f t(string) }); var g = f`, `g`, `var g3.g func(x struct{f g3.t(string)})`},
|
||||
|
|
@ -489,7 +489,7 @@ func TestUsesInfo(t *testing.T) {
|
|||
|
||||
// generic types must be sanitized
|
||||
// (need to use sufficiently nested types to provoke unexpanded types)
|
||||
// TODO(gri) add analogous test for constants, once T(int) is accepted as constant type
|
||||
{`package g0; func _() { _ = x }; type t(type P) P; const x = (t(int))(42)`, `x`, `const g0.x g0.t(int)`},
|
||||
{`package g1; func _() { _ = x }; type t(type P) P; var x = (t(int))(42)`, `x`, `var g1.x g1.t(int)`},
|
||||
{`package g2; func _() { type _ x }; type t(type P) P; type x struct{ f t(int) }`, `x`, `type g2.x struct{f g2.t(int)}`},
|
||||
{`package g3; func _() { _ = f }; type t(type P) P; func f(x struct{ f t(string) })`, `f`, `func g3.f(x struct{f g3.t(string)})`},
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import (
|
|||
"sort"
|
||||
)
|
||||
|
||||
// isNamed reports whether typ has a name.
|
||||
// isNamed may be called with types that are not fully set up.
|
||||
func isNamed(typ Type) bool {
|
||||
switch typ.(type) {
|
||||
case *Basic, *Named, *instance:
|
||||
|
|
@ -44,14 +46,22 @@ func isComplex(typ Type) bool { return is(typ, IsComplex) }
|
|||
func isNumeric(typ Type) bool { return is(typ, IsNumeric) }
|
||||
func isString(typ Type) bool { return is(typ, IsString) }
|
||||
|
||||
// isTyped reports whether typ is typed; i.e., not an untyped
|
||||
// constant or boolean. isTyped may be called with types that
|
||||
// are not fully set up.
|
||||
func isTyped(typ Type) bool {
|
||||
t := typ.Basic()
|
||||
// isTyped is called with types that are not fully
|
||||
// set up. Must not call Basic()!
|
||||
// A *Named or *instance type is always typed, so
|
||||
// we only need to check if we have a true *Basic
|
||||
// type.
|
||||
t, _ := typ.(*Basic)
|
||||
return t == nil || t.info&IsUntyped == 0
|
||||
}
|
||||
|
||||
// isUntyped(typ) is the same as !isTyped(typ).
|
||||
func isUntyped(typ Type) bool {
|
||||
t := typ.Basic()
|
||||
return t != nil && t.info&IsUntyped != 0
|
||||
return !isTyped(typ)
|
||||
}
|
||||
|
||||
func isOrdered(typ Type) bool { return is(typ, IsOrdered) }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
package p
|
||||
|
||||
type E(type P) struct {
|
||||
(E /* ERROR illegal cycle */ (P))
|
||||
}
|
||||
type T(type P) P
|
||||
|
||||
const _ T(int) = 0
|
||||
|
|
|
|||
|
|
@ -19,12 +19,16 @@ type Type interface {
|
|||
|
||||
// Under returns the true expanded underlying type.
|
||||
// If it doesn't exist, the result is Typ[Invalid].
|
||||
// Under must only be called when a type is known
|
||||
// to be fully set up.
|
||||
Under() Type
|
||||
|
||||
// String returns a string representation of a type.
|
||||
String() string
|
||||
|
||||
// Converters
|
||||
// A converter must only be called when a type is
|
||||
// known to be fully set up.
|
||||
Basic() *Basic
|
||||
Array() *Array
|
||||
Slice() *Slice
|
||||
|
|
@ -698,7 +702,19 @@ type instance struct {
|
|||
aType
|
||||
}
|
||||
|
||||
func (t *instance) Named() *Named { return t.expand().Named() }
|
||||
// Converter methods
|
||||
func (t *instance) Basic() *Basic { return t.Under().Basic() }
|
||||
func (t *instance) Array() *Array { return t.Under().Array() }
|
||||
func (t *instance) Slice() *Slice { return t.Under().Slice() }
|
||||
func (t *instance) Struct() *Struct { return t.Under().Struct() }
|
||||
func (t *instance) Pointer() *Pointer { return t.Under().Pointer() }
|
||||
func (t *instance) Tuple() *Tuple { return t.Under().Tuple() }
|
||||
func (t *instance) Signature() *Signature { return t.Under().Signature() }
|
||||
func (t *instance) Interface() *Interface { return t.Under().Interface() }
|
||||
func (t *instance) Map() *Map { return t.Under().Map() }
|
||||
func (t *instance) Chan() *Chan { return t.Under().Chan() }
|
||||
func (t *instance) Named() *Named { return t.expand().Named() }
|
||||
func (t *instance) TypeParam() *TypeParam { return t.Under().TypeParam() }
|
||||
|
||||
// expand returns the instantiated (= expanded) type of t.
|
||||
// The result is either an instantiated *Named type, or
|
||||
|
|
@ -775,15 +791,8 @@ func (t *Map) Under() Type { return t }
|
|||
func (t *Chan) Under() Type { return t }
|
||||
|
||||
// see decl.go for implementation of Named.Under
|
||||
|
||||
func (t *TypeParam) Under() Type { return t }
|
||||
func (t *instance) Under() Type {
|
||||
typ := t.expand()
|
||||
if n, _ := typ.(*Named); n != nil {
|
||||
return n.Under()
|
||||
}
|
||||
return typ
|
||||
}
|
||||
func (t *instance) Under() Type { return t.expand().Under() }
|
||||
|
||||
func (t *Basic) String() string { return TypeString(t, nil) }
|
||||
func (t *Array) String() string { return TypeString(t, nil) }
|
||||
|
|
|
|||
Loading…
Reference in New Issue