aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types/type.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/types/type.go')
-rw-r--r--src/cmd/compile/internal/types/type.go46
1 files changed, 46 insertions, 0 deletions
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
+}