aboutsummaryrefslogtreecommitdiff
path: root/src/go/types/alias.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/go/types/alias.go')
-rw-r--r--src/go/types/alias.go37
1 files changed, 21 insertions, 16 deletions
diff --git a/src/go/types/alias.go b/src/go/types/alias.go
index 8333a4d9c9..6043c0a984 100644
--- a/src/go/types/alias.go
+++ b/src/go/types/alias.go
@@ -23,11 +23,14 @@ type Alias struct {
// NewAlias creates a new Alias type with the given type name and rhs.
// rhs must not be nil.
func NewAlias(obj *TypeName, rhs Type) *Alias {
- return (*Checker)(nil).newAlias(obj, rhs)
+ alias := (*Checker)(nil).newAlias(obj, rhs)
+ // Ensure that alias.actual is set (#65455).
+ unalias(alias)
+ return alias
}
func (a *Alias) Obj() *TypeName { return a.obj }
-func (a *Alias) Underlying() Type { return a.actual.Underlying() }
+func (a *Alias) Underlying() Type { return unalias(a).Underlying() }
func (a *Alias) String() string { return TypeString(a, nil) }
// Type accessors
@@ -38,24 +41,26 @@ func (a *Alias) String() string { return TypeString(a, nil) }
// Consequently, the result is never an alias type.
func Unalias(t Type) Type {
if a0, _ := t.(*Alias); a0 != nil {
- if a0.actual != nil {
- return a0.actual
- }
- for a := a0; ; {
- t = a.fromRHS
- a, _ = t.(*Alias)
- if a == nil {
- break
- }
- }
- if t == nil {
- panic(fmt.Sprintf("non-terminated alias %s", a0.obj.name))
- }
- a0.actual = t
+ return unalias(a0)
}
return t
}
+func unalias(a0 *Alias) Type {
+ if a0.actual != nil {
+ return a0.actual
+ }
+ var t Type
+ for a := a0; a != nil; a, _ = t.(*Alias) {
+ t = a.fromRHS
+ }
+ if t == nil {
+ panic(fmt.Sprintf("non-terminated alias %s", a0.obj.name))
+ }
+ a0.actual = t
+ return t
+}
+
// asNamed returns t as *Named if that is t's
// actual type. It returns nil otherwise.
func asNamed(t Type) *Named {