Source file src/go/types/alias.go
1 // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT. 2 // Source: ../../cmd/compile/internal/types2/alias.go 3 4 // Copyright 2023 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 package types 9 10 import "fmt" 11 12 // An Alias represents an alias type. 13 // Whether or not Alias types are created is controlled by the 14 // gotypesalias setting with the GODEBUG environment variable. 15 // For gotypesalias=1, alias declarations produce an Alias type. 16 // Otherwise, the alias information is only in the type name, 17 // which points directly to the actual (aliased) type. 18 type Alias struct { 19 obj *TypeName // corresponding declared alias object 20 tparams *TypeParamList // type parameters, or nil 21 fromRHS Type // RHS of type alias declaration; may be an alias 22 actual Type // actual (aliased) type; never an alias 23 } 24 25 // NewAlias creates a new Alias type with the given type name and rhs. 26 // rhs must not be nil. 27 func NewAlias(obj *TypeName, rhs Type) *Alias { 28 alias := (*Checker)(nil).newAlias(obj, rhs) 29 // Ensure that alias.actual is set (#65455). 30 alias.cleanup() 31 return alias 32 } 33 34 func (a *Alias) Obj() *TypeName { return a.obj } 35 func (a *Alias) Underlying() Type { return unalias(a).Underlying() } 36 func (a *Alias) String() string { return TypeString(a, nil) } 37 38 // Rhs returns the type R on the right-hand side of an alias 39 // declaration "type A = R", which may be another alias. 40 func (a *Alias) Rhs() Type { return a.fromRHS } 41 42 // Unalias returns t if it is not an alias type; 43 // otherwise it follows t's alias chain until it 44 // reaches a non-alias type which is then returned. 45 // Consequently, the result is never an alias type. 46 func Unalias(t Type) Type { 47 if a0, _ := t.(*Alias); a0 != nil { 48 return unalias(a0) 49 } 50 return t 51 } 52 53 func unalias(a0 *Alias) Type { 54 if a0.actual != nil { 55 return a0.actual 56 } 57 var t Type 58 for a := a0; a != nil; a, _ = t.(*Alias) { 59 t = a.fromRHS 60 } 61 if t == nil { 62 panic(fmt.Sprintf("non-terminated alias %s", a0.obj.name)) 63 } 64 65 // Memoize the type only if valid. 66 // In the presence of unfinished cyclic declarations, Unalias 67 // would otherwise latch the invalid value (#66704). 68 // TODO(adonovan): rethink, along with checker.typeDecl's use 69 // of Invalid to mark unfinished aliases. 70 if t != Typ[Invalid] { 71 a0.actual = t 72 } 73 74 return t 75 } 76 77 // asNamed returns t as *Named if that is t's 78 // actual type. It returns nil otherwise. 79 func asNamed(t Type) *Named { 80 n, _ := Unalias(t).(*Named) 81 return n 82 } 83 84 // newAlias creates a new Alias type with the given type name and rhs. 85 // rhs must not be nil. 86 func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias { 87 assert(rhs != nil) 88 a := &Alias{obj, nil, rhs, nil} 89 if obj.typ == nil { 90 obj.typ = a 91 } 92 93 // Ensure that a.actual is set at the end of type checking. 94 if check != nil { 95 check.needsCleanup(a) 96 } 97 98 return a 99 } 100 101 func (a *Alias) cleanup() { 102 // Ensure a.actual is set before types are published, 103 // so Unalias is a pure "getter", not a "setter". 104 actual := Unalias(a) 105 106 if actual == Typ[Invalid] { 107 // We don't set a.actual to Typ[Invalid] during type checking, 108 // as it may indicate that the RHS is not fully set up. 109 a.actual = actual 110 } 111 } 112