]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/types2/alias.go
go/types, types2: implement Alias proposal (export API)
[gostls13.git] / src / cmd / compile / internal / types2 / alias.go
1 // Copyright 2023 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 types2
6
7 import "fmt"
8
9 // An Alias represents an alias type.
10 // Whether or not Alias types are created is controlled by the
11 // gotypesalias setting with the GODEBUG environment variable.
12 // For gotypesalias=1, alias declarations produce an Alias type.
13 // Otherwise, the alias information is only in the type name,
14 // which points directly to the actual (aliased) type.
15 type Alias struct {
16         obj     *TypeName // corresponding declared alias object
17         fromRHS Type      // RHS of type alias declaration; may be an alias
18         actual  Type      // actual (aliased) type; never an alias
19 }
20
21 // NewAlias creates a new Alias type with the given type name and rhs.
22 // rhs must not be nil.
23 func NewAlias(obj *TypeName, rhs Type) *Alias {
24         return (*Checker)(nil).newAlias(obj, rhs)
25 }
26
27 func (a *Alias) Obj() *TypeName   { return a.obj }
28 func (a *Alias) Underlying() Type { return a.actual.Underlying() }
29 func (a *Alias) String() string   { return TypeString(a, nil) }
30
31 // Type accessors
32
33 // Unalias returns t if it is not an alias type;
34 // otherwise it follows t's alias chain until it
35 // reaches a non-alias type which is then returned.
36 // Consequently, the result is never an alias type.
37 func Unalias(t Type) Type {
38         if a0, _ := t.(*Alias); a0 != nil {
39                 if a0.actual != nil {
40                         return a0.actual
41                 }
42                 for a := a0; ; {
43                         t = a.fromRHS
44                         a, _ = t.(*Alias)
45                         if a == nil {
46                                 break
47                         }
48                 }
49                 if t == nil {
50                         panic(fmt.Sprintf("non-terminated alias %s", a0.obj.name))
51                 }
52                 a0.actual = t
53         }
54         return t
55 }
56
57 // asNamed returns t as *Named if that is t's
58 // actual type. It returns nil otherwise.
59 func asNamed(t Type) *Named {
60         n, _ := Unalias(t).(*Named)
61         return n
62 }
63
64 // newAlias creates a new Alias type with the given type name and rhs.
65 // rhs must not be nil.
66 func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias {
67         assert(rhs != nil)
68         a := &Alias{obj, rhs, nil}
69         if obj.typ == nil {
70                 obj.typ = a
71         }
72
73         // Ensure that a.actual is set at the end of type checking.
74         if check != nil {
75                 check.needsCleanup(a)
76         }
77
78         return a
79 }
80
81 func (a *Alias) cleanup() {
82         Unalias(a)
83 }