diff options
Diffstat (limited to 'src/go/types/typestring.go')
-rw-r--r-- | src/go/types/typestring.go | 110 |
1 files changed, 67 insertions, 43 deletions
diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index fe27f0f276..c0c69624ec 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -158,12 +158,19 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteString("func") writeSignature(buf, t, qf, visited) - case *_Sum: - for i, t := range t.types { + case *Union: + if t.IsEmpty() { + buf.WriteString("⊥") + break + } + for i, t := range t.terms { if i > 0 { - buf.WriteString(", ") + buf.WriteByte('|') } - writeType(buf, t, qf, visited) + if t.tilde { + buf.WriteByte('~') + } + writeType(buf, t.typ, qf, visited) } case *Interface: @@ -183,7 +190,8 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { if gcCompatibilityMode { // print flattened interface // (useful to compare against gc-generated interfaces) - for i, m := range t.allMethods { + tset := t.typeSet() + for i, m := range tset.methods { if i > 0 { buf.WriteString("; ") } @@ -191,12 +199,12 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } - if !empty && t.allTypes != nil { + if !empty && tset.types != nil { buf.WriteString("; ") } - if t.allTypes != nil { + if tset.types != nil { buf.WriteString("type ") - writeType(buf, t.allTypes, qf, visited) + writeType(buf, tset.types, qf, visited) } } else { // print explicit interface methods and embedded types @@ -208,14 +216,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } - if !empty && t.types != nil { - buf.WriteString("; ") - } - if t.types != nil { - buf.WriteString("type ") - writeType(buf, t.types, qf, visited) - empty = false - } if !empty && len(t.embeddeds) > 0 { buf.WriteString("; ") } @@ -227,7 +227,9 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { empty = false } } - if t.allMethods == nil || len(t.methods) > len(t.allMethods) { + // print /* incomplete */ if needed to satisfy existing tests + // TODO(gri) get rid of this eventually + if debug && t.tset == nil { if !empty { buf.WriteByte(' ') } @@ -268,39 +270,40 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } case *Named: + if t.instance != nil { + buf.WriteByte(instanceMarker) + } writeTypeName(buf, t.obj, qf) if t.targs != nil { // instantiated type buf.WriteByte('[') writeTypeList(buf, t.targs, qf, visited) buf.WriteByte(']') - } else if t.tparams != nil { + } else if t.TParams().Len() != 0 { // parameterized type - writeTParamList(buf, t.tparams, qf, visited) + writeTParamList(buf, t.TParams().list(), qf, visited) } - case *_TypeParam: + case *TypeParam: s := "?" if t.obj != nil { + // Optionally write out package for typeparams (like Named). + // TODO(rfindley): this is required for import/export, so + // we maybe need a separate function that won't be changed + // for debugging purposes. + if t.obj.pkg != nil { + writePackage(buf, t.obj.pkg, qf) + } s = t.obj.name } buf.WriteString(s + subscript(t.id)) - case *instance: - buf.WriteByte(instanceMarker) // indicate "non-evaluated" syntactic instance - writeTypeName(buf, t.base.obj, qf) - buf.WriteByte('[') - writeTypeList(buf, t.targs, qf, visited) - buf.WriteByte(']') - - case *bottom: - buf.WriteString("⊥") - case *top: buf.WriteString("⊤") default: // For externally defined implementations of Type. + // Note: In this case cycles won't be caught. buf.WriteString(t.String()) } } @@ -321,7 +324,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited for i, p := range list { // TODO(rFindley) support 'any' sugar here. var b Type = &emptyInterface - if t, _ := p.typ.(*_TypeParam); t != nil && t.bound != nil { + if t, _ := p.typ.(*TypeParam); t != nil && t.bound != nil { b = t.bound } if i > 0 { @@ -334,7 +337,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited } prev = b - if t, _ := p.typ.(*_TypeParam); t != nil { + if t, _ := p.typ.(*TypeParam); t != nil { writeType(buf, t, qf, visited) } else { buf.WriteString(p.name) @@ -348,17 +351,38 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited } func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { - s := "<Named w/o object>" - if obj != nil { - if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) + if obj == nil { + buf.WriteString("<Named w/o object>") + return + } + if obj.pkg != nil { + writePackage(buf, obj.pkg, qf) + } + buf.WriteString(obj.name) + + if instanceHashing != 0 { + // For local defined types, use the (original!) TypeName's scope + // numbers to disambiguate. + typ := obj.typ.(*Named) + // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes + // and whether the loop can iterate more than twice. + // (It seems somehow connected to instance types.) + for typ.orig != typ { + typ = typ.orig } - // TODO(gri): function-local named types should be displayed - // differently from named types at package level to avoid - // ambiguity. - s = obj.name + writeScopeNumbers(buf, typ.obj.parent) + } +} + +// writeScopeNumbers writes the number sequence for this scope to buf +// in the form ".i.j.k" where i, j, k, etc. stand for scope numbers. +// If a scope is nil or has no parent (such as a package scope), nothing +// is written. +func writeScopeNumbers(buf *bytes.Buffer, s *Scope) { + if s != nil && s.number > 0 { + writeScopeNumbers(buf, s.parent) + fmt.Fprintf(buf, ".%d", s.number) } - buf.WriteString(s) } func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) { @@ -403,8 +427,8 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { } func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { - if sig.tparams != nil { - writeTParamList(buf, sig.tparams, qf, visited) + if sig.TParams().Len() != 0 { + writeTParamList(buf, sig.TParams().list(), qf, visited) } writeTuple(buf, sig.params, sig.variadic, qf, visited) |