mirror of
https://github.com/golang/go
synced 2024-11-11 23:40:22 -07:00
cmd/compile/internal/types2: more systematic error handling in typeWriter
When using a typeWriter for debugging/error message type strings, it shouldn't crash in the presence of type-checker internal bugs. But when a typeHasher is used, we don't want to silently ignore errors. Introduce an error method that panics in type hashing mode but prints an error value otherwise. Also fixed an incorrect 'if' statement in tParamList. Change-Id: I26c8b8e0b14396e91ad71bf903e36ce1ca55839e Reviewed-on: https://go-review.googlesource.com/c/go/+/346009 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
b06cfe9b25
commit
3342aa5f51
@ -55,6 +55,14 @@ func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) {
|
||||
newTypeWriter(buf, qf).typ(typ)
|
||||
}
|
||||
|
||||
// WriteSignature writes the representation of the signature sig to buf,
|
||||
// without a leading "func" keyword.
|
||||
// The Qualifier controls the printing of
|
||||
// package-level objects, and may be nil.
|
||||
func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
|
||||
newTypeWriter(buf, qf).signature(sig)
|
||||
}
|
||||
|
||||
// instanceMarker is the prefix for an instantiated type in unexpanded form.
|
||||
const instanceMarker = '#'
|
||||
|
||||
@ -76,10 +84,16 @@ func newTypeHasher(buf *bytes.Buffer) *typeWriter {
|
||||
func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) }
|
||||
func (w *typeWriter) string(s string) { w.buf.WriteString(s) }
|
||||
func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) }
|
||||
func (w *typeWriter) error(msg string) {
|
||||
if w.hash {
|
||||
panic(msg)
|
||||
}
|
||||
w.string("<" + msg + ">")
|
||||
}
|
||||
|
||||
func (w *typeWriter) typ(typ Type) {
|
||||
if w.seen[typ] {
|
||||
w.writef("○%T", goTypeName(typ)) // cycle to typ
|
||||
w.error("cycle to " + goTypeName(typ))
|
||||
return
|
||||
}
|
||||
w.seen[typ] = true
|
||||
@ -87,7 +101,7 @@ func (w *typeWriter) typ(typ Type) {
|
||||
|
||||
switch t := typ.(type) {
|
||||
case nil:
|
||||
w.string("<nil>")
|
||||
w.error("nil")
|
||||
|
||||
case *Basic:
|
||||
// exported basic types go into package unsafe
|
||||
@ -143,7 +157,8 @@ func (w *typeWriter) typ(typ Type) {
|
||||
// Unions only appear as (syntactic) embedded elements
|
||||
// in interfaces and syntactically cannot be empty.
|
||||
if t.Len() == 0 {
|
||||
panic("empty union")
|
||||
w.error("empty union")
|
||||
break
|
||||
}
|
||||
for i, t := range t.terms {
|
||||
if i > 0 {
|
||||
@ -196,7 +211,8 @@ func (w *typeWriter) typ(typ Type) {
|
||||
case RecvOnly:
|
||||
s = "<-chan "
|
||||
default:
|
||||
unreachable()
|
||||
w.error("unknown channel direction")
|
||||
break
|
||||
}
|
||||
w.string(s)
|
||||
if parens {
|
||||
@ -225,21 +241,21 @@ func (w *typeWriter) typ(typ Type) {
|
||||
}
|
||||
|
||||
case *TypeParam:
|
||||
s := "?"
|
||||
if t.obj != nil {
|
||||
// Optionally write out package for typeparams (like Named).
|
||||
// TODO(danscales): 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(w.buf, t.obj.pkg, w.qf)
|
||||
}
|
||||
s = t.obj.name
|
||||
if t.obj == nil {
|
||||
w.error("unnamed type parameter")
|
||||
break
|
||||
}
|
||||
w.string(s + subscript(t.id))
|
||||
// Optionally write out package for typeparams (like Named).
|
||||
// TODO(danscales): 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(w.buf, t.obj.pkg, w.qf)
|
||||
}
|
||||
w.string(t.obj.name + subscript(t.id))
|
||||
|
||||
case *top:
|
||||
w.string("⊤")
|
||||
w.error("⊤")
|
||||
|
||||
default:
|
||||
// For externally defined implementations of Type.
|
||||
@ -266,26 +282,20 @@ func (w *typeWriter) tParamList(list []*TypeParam) {
|
||||
// Determine the type parameter and its constraint.
|
||||
// list is expected to hold type parameter names,
|
||||
// but don't crash if that's not the case.
|
||||
var bound Type
|
||||
if tpar != nil {
|
||||
bound = tpar.bound // should not be nil but we want to see it if it is
|
||||
if tpar == nil {
|
||||
w.error("nil type parameter")
|
||||
continue
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
if bound != prev {
|
||||
if tpar.bound != prev {
|
||||
// bound changed - write previous one before advancing
|
||||
w.byte(' ')
|
||||
w.typ(prev)
|
||||
}
|
||||
w.string(", ")
|
||||
}
|
||||
prev = bound
|
||||
|
||||
if tpar != nil {
|
||||
w.typ(tpar)
|
||||
} else {
|
||||
w.string(tpar.obj.name)
|
||||
}
|
||||
prev = tpar.bound
|
||||
w.typ(tpar)
|
||||
}
|
||||
if prev != nil {
|
||||
w.byte(' ')
|
||||
@ -295,11 +305,6 @@ func (w *typeWriter) tParamList(list []*TypeParam) {
|
||||
}
|
||||
|
||||
func (w *typeWriter) typeName(obj *TypeName) {
|
||||
if obj == nil {
|
||||
assert(!w.hash) // we need an object for type hashing
|
||||
w.string("<Named w/o object>")
|
||||
return
|
||||
}
|
||||
if obj.pkg != nil {
|
||||
writePackage(w.buf, obj.pkg, w.qf)
|
||||
}
|
||||
@ -352,7 +357,8 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
|
||||
// special case:
|
||||
// append(s, "foo"...) leads to signature func([]byte, string...)
|
||||
if t := asBasic(typ); t == nil || t.kind != String {
|
||||
panic("expected string type")
|
||||
w.error("expected string type")
|
||||
continue
|
||||
}
|
||||
w.typ(typ)
|
||||
w.string("...")
|
||||
@ -365,14 +371,6 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
|
||||
w.byte(')')
|
||||
}
|
||||
|
||||
// WriteSignature writes the representation of the signature sig to buf,
|
||||
// without a leading "func" keyword.
|
||||
// The Qualifier controls the printing of
|
||||
// package-level objects, and may be nil.
|
||||
func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
|
||||
newTypeWriter(buf, qf).signature(sig)
|
||||
}
|
||||
|
||||
func (w *typeWriter) signature(sig *Signature) {
|
||||
if sig.TParams().Len() != 0 {
|
||||
w.tParamList(sig.TParams().list())
|
||||
|
Loading…
Reference in New Issue
Block a user