Skip to content

Commit aa1f068

Browse files
committed
[dev.typealias] go/types: improved Object printing
- added internal isAlias predicated and test - use it for improved Object printing - when printing a basic type object, don't repeat type name (i.e., print "type int" rather than "type int int") - added another test to testdata/decls4.src For golang#18130. Change-Id: Ice9517c0065a2cc465c6d12f87cd27c01ef801e6 Reviewed-on: https://go-review.googlesource.com/35093 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alan Donovan <adonovan@google.com>
1 parent c80748e commit aa1f068

File tree

5 files changed

+85
-8
lines changed

5 files changed

+85
-8
lines changed

src/go/types/example_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,10 @@ func fib(x int) int {
239239
// type S string:
240240
// defined at fib.go:4:6
241241
// used at 6:23
242-
// type int int:
242+
// type int:
243243
// defined at -
244244
// used at 8:12, 8:17
245-
// type string string:
245+
// type string:
246246
// defined at -
247247
// used at 4:8
248248
// var b S:

src/go/types/object.go

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,30 @@ func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
163163
return &TypeName{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
164164
}
165165

166+
func (obj *TypeName) isAlias() bool {
167+
switch t := obj.typ.(type) {
168+
case nil:
169+
return false
170+
case *Basic:
171+
// It would seem that we should be able to look for different names here;
172+
// but the names of universeByte/Rune are "byte" and "rune", respectively.
173+
// We do this so that we get better error messages. However, general alias
174+
// types don't have that name information and thus behave differently when
175+
// reporting errors (we won't see the alias name, only the original name).
176+
// Maybe we should remove the special handling for the predeclared types
177+
// as well to be consistent (at the cost of slightly less clear error
178+
// messages when byte/rune are involved).
179+
// This also plays out in the implementation of the Identical(Type, Type)
180+
// predicate.
181+
// TODO(gri) consider possible clean up
182+
return t == universeByte || t == universeRune
183+
case *Named:
184+
return obj != t.obj
185+
default:
186+
return true
187+
}
188+
}
189+
166190
// A Variable represents a declared variable (including function parameters and results, and struct fields).
167191
type Var struct {
168192
object
@@ -242,7 +266,9 @@ type Nil struct {
242266
}
243267

244268
func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
269+
var tname *TypeName
245270
typ := obj.Type()
271+
246272
switch obj := obj.(type) {
247273
case *PkgName:
248274
fmt.Fprintf(buf, "package %s", obj.Name())
@@ -255,8 +281,8 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
255281
buf.WriteString("const")
256282

257283
case *TypeName:
284+
tname = obj
258285
buf.WriteString("type")
259-
typ = typ.Underlying()
260286

261287
case *Var:
262288
if obj.isField {
@@ -297,12 +323,26 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
297323
}
298324
buf.WriteString(obj.Name())
299325

300-
// TODO(gri) indicate type alias if we have one
326+
if typ == nil {
327+
return
328+
}
301329

302-
if typ != nil {
303-
buf.WriteByte(' ')
304-
WriteType(buf, typ, qf)
330+
if tname != nil {
331+
// We have a type object: Don't print anything more for
332+
// basic types since there's no more information (names
333+
// are the same; see also comment in TypeName.isAlias).
334+
if _, ok := typ.(*Basic); ok {
335+
return
336+
}
337+
if tname.isAlias() {
338+
buf.WriteString(" =")
339+
} else {
340+
typ = typ.Underlying()
341+
}
305342
}
343+
344+
buf.WriteByte(' ')
345+
WriteType(buf, typ, qf)
306346
}
307347

308348
func writePackage(buf *bytes.Buffer, pkg *Package, qf Qualifier) {

src/go/types/object_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package types
6+
7+
import "testing"
8+
9+
func TestIsAlias(t *testing.T) {
10+
check := func(obj *TypeName, want bool) {
11+
if got := obj.isAlias(); got != want {
12+
t.Errorf("%v: got isAlias = %v; want %v", obj, got, want)
13+
}
14+
}
15+
16+
// predeclared types
17+
for _, name := range Universe.Names() {
18+
if obj, _ := Universe.Lookup(name).(*TypeName); obj != nil {
19+
check(obj, name == "byte" || name == "rune")
20+
}
21+
}
22+
23+
// various other types
24+
t0 := NewTypeName(0, nil, "t0", nil)
25+
check(t0, false) // no type yet
26+
27+
t1 := NewTypeName(0, nil, "t1", nil)
28+
n1 := NewNamed(t1, new(Struct), nil)
29+
check(t1, false) // type name refers to named type and vice versa
30+
31+
t2 := NewTypeName(0, nil, "t2", new(Interface))
32+
check(t2, true) // type name refers to unnamed type
33+
34+
t3 := NewTypeName(0, nil, "t3", n1)
35+
check(t3, true) // type name refers to named type with different type name (true alias)
36+
}

src/go/types/predicates.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
139139
case *Basic:
140140
// Basic types are singletons except for the rune and byte
141141
// aliases, thus we cannot solely rely on the x == y check
142-
// above.
142+
// above. See also comment in TypeName.isAlias.
143143
if y, ok := y.(*Basic); ok {
144144
return x.kind == y.kind
145145
}

src/go/types/testdata/decls4.src

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func (Ai /* ERROR "invalid receiver" */) m1() {}
6363
func (T0) m1() {}
6464
func (A0) m1 /* ERROR already declared */ () {}
6565
func (A0) m2 () {}
66+
func (A3 /* ERROR invalid receiver */ ) m1 () {}
6667
func (A10 /* ERROR invalid receiver */ ) m1() {}
6768

6869
// x0 has methods m1, m2 declared via receiver type names T0 and A0

0 commit comments

Comments
 (0)