From ccf95f17dd87683d915f7b11d88530b5f8f8efa2 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 13:27:57 -0400 Subject: [PATCH] [dev.typeparams] go/types: support local defined types This is a port of CL 327170 to go/types. Tests were not ported; they can be added later. Change-Id: Ic9fd681ac06dd187c1715efaf882b11353bc395a Reviewed-on: https://go-review.googlesource.com/c/go/+/335113 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/subst.go | 5 +++++ src/go/types/typestring.go | 36 ++++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 41ffcd0d1e4..d8388a948b8 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -428,14 +428,19 @@ func (subst *subster) typ(typ Type) Type { return typ } +var instanceHashing = 0 + // TODO(gri) Eventually, this should be more sophisticated. // It won't work correctly for locally declared types. func instantiatedHash(typ *Named, targs []Type) string { + assert(instanceHashing == 0) + instanceHashing++ var buf bytes.Buffer writeTypeName(&buf, typ.obj, nil) buf.WriteByte('[') writeTypeList(&buf, targs, nil, nil) buf.WriteByte(']') + instanceHashing-- // With respect to the represented type, whether a // type is fully expanded or stored as instance diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index aef5e2013bd..f348d185c55 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -348,17 +348,33 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited } func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { - s := "" - if obj != nil { - if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) - } - // TODO(gri): function-local named types should be displayed - // differently from named types at package level to avoid - // ambiguity. - s = obj.name + if obj == nil { + buf.WriteString("") + 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 position + // to disambiguate. This is overkill, and could probably instead + // just be the pointer value (if we assume a non-moving GC) or + // a unique ID (like cmd/compile uses). But this works for now, + // and is convenient for debugging. + + // TODO(mdempsky): I still don't fully understand why typ.orig.orig + // can differ from typ.orig, or whether looping more than twice is + // ever necessary. + typ := obj.typ.(*Named) + for typ.orig != typ { + typ = typ.orig + } + if orig := typ.obj; orig.pkg != nil && orig.parent != orig.pkg.scope { + fmt.Fprintf(buf, "@%q", orig.pos) + } } - buf.WriteString(s) } func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) {