aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2021-06-09 19:30:16 -0700
committerKeith Randall <khr@golang.org>2021-07-21 21:04:15 +0000
commita7a17f0ca86d252dc1ef20b5852c352ade5f8610 (patch)
treefdc726eb6a687dfb988e927fdef467cd393bfaa1 /src/cmd/compile/internal/types
parent897970688b326f7baa8ad8e3330fb552d94b0014 (diff)
downloadgo-a7a17f0ca86d252dc1ef20b5852c352ade5f8610.tar.gz
go-a7a17f0ca86d252dc1ef20b5852c352ade5f8610.zip
[dev.typeparams] cmd/compile: introduce named gcshape types
Still 1-1 with real types, but now with their own names! Shape types are implicitly convertible to (and convertible from) the types they represent. Change-Id: I0133a8d8fbeb369380574b075a32b3c987e314d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/335170 Run-TryBot: Keith Randall <khr@golang.org> Trust: Keith Randall <khr@golang.org> Trust: Dan Scales <danscales@google.com> Reviewed-by: Dan Scales <danscales@google.com>
Diffstat (limited to 'src/cmd/compile/internal/types')
-rw-r--r--src/cmd/compile/internal/types/identity.go9
-rw-r--r--src/cmd/compile/internal/types/type.go46
2 files changed, 55 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go
index dde9f51856..0a78092f07 100644
--- a/src/cmd/compile/internal/types/identity.go
+++ b/src/cmd/compile/internal/types/identity.go
@@ -29,6 +29,14 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b
return false
}
if t1.sym != nil || t2.sym != nil {
+ if t1.HasShape() || t2.HasShape() {
+ switch t1.kind {
+ case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64, TBOOL, TSTRING, TUNSAFEPTR:
+ return true
+ }
+ // fall through to unnamed type comparison for complex types.
+ goto cont
+ }
// Special case: we keep byte/uint8 and rune/int32
// separate for error messages. Treat them as equal.
switch t1.kind {
@@ -40,6 +48,7 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b
return false
}
}
+cont:
// Any cyclic type must go through a named type, and if one is
// named, it is only identical to the other if they are the
diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go
index 28312111ad..e6ae0e7bc1 100644
--- a/src/cmd/compile/internal/types/type.go
+++ b/src/cmd/compile/internal/types/type.go
@@ -210,6 +210,7 @@ const (
typeDeferwidth // width computation has been deferred and type is on deferredTypeStack
typeRecur
typeHasTParam // there is a typeparam somewhere in the type (generic function or type)
+ typeIsShape // represents a set of closely related types, for generics
)
func (t *Type) NotInHeap() bool { return t.flags&typeNotInHeap != 0 }
@@ -218,12 +219,14 @@ func (t *Type) Noalg() bool { return t.flags&typeNoalg != 0 }
func (t *Type) Deferwidth() bool { return t.flags&typeDeferwidth != 0 }
func (t *Type) Recur() bool { return t.flags&typeRecur != 0 }
func (t *Type) HasTParam() bool { return t.flags&typeHasTParam != 0 }
+func (t *Type) IsShape() bool { return t.flags&typeIsShape != 0 }
func (t *Type) SetNotInHeap(b bool) { t.flags.set(typeNotInHeap, b) }
func (t *Type) SetBroke(b bool) { t.flags.set(typeBroke, b) }
func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) }
func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) }
func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) }
+func (t *Type) SetIsShape(b bool) { t.flags.set(typeIsShape, b) }
// Generic types should never have alg functions.
func (t *Type) SetHasTParam(b bool) { t.flags.set(typeHasTParam, b); t.flags.set(typeNoalg, b) }
@@ -2147,3 +2150,46 @@ var (
)
var SimType [NTYPE]Kind
+
+// Reports whether t has a shape type anywere.
+func (t *Type) HasShape() bool {
+ return t.HasShape1(map[*Type]bool{})
+}
+func (t *Type) HasShape1(visited map[*Type]bool) bool {
+ if t.IsShape() {
+ return true
+ }
+ if visited[t] {
+ return false
+ }
+ visited[t] = true
+ if t.Sym() != nil {
+ for _, u := range t.RParams() {
+ if u.HasShape1(visited) {
+ return true
+ }
+ }
+ }
+ switch t.Kind() {
+ case TPTR, TARRAY, TSLICE, TCHAN:
+ return t.Elem().HasShape1(visited)
+ case TMAP:
+ return t.Elem().HasShape1(visited) || t.Key().HasShape1(visited)
+ case TSTRUCT:
+ for _, f := range t.FieldSlice() {
+ if f.Type.HasShape1(visited) {
+ return true
+ }
+ }
+ case TFUNC:
+ for _, a := range RecvsParamsResults {
+ for _, f := range a(t).FieldSlice() {
+ if f.Type.HasShape1(visited) {
+ return true
+ }
+ }
+ }
+ // TODO: TINTER - check methods?
+ }
+ return false
+}