1 // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
2 // Source: ../../cmd/compile/internal/types2/typeparam.go
3 4 // Copyright 2011 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 "sync/atomic"
11 12 // Note: This is a uint32 rather than a uint64 because the
13 // respective 64 bit atomic instructions are not available
14 // on all platforms.
15 var lastID atomic.Uint32
16 17 // nextID returns a value increasing monotonically by 1 with
18 // each call, starting with 1. It may be called concurrently.
19 func nextID() uint64 { return uint64(lastID.Add(1)) }
20 21 // A TypeParam represents the type of a type parameter in a generic declaration.
22 //
23 // A TypeParam has a name; use the [TypeParam.Obj] method to access
24 // its [TypeName] object.
25 type TypeParam struct {
26 check *Checker // for lazy type bound completion
27 id uint64 // unique id, for debugging only
28 obj *TypeName // corresponding type name
29 index int // type parameter index in source order, starting at 0
30 bound Type // any type, but underlying is eventually *Interface for correct programs (see TypeParam.iface)
31 }
32 33 // NewTypeParam returns a new TypeParam. Type parameters may be set on a Named
34 // type by calling SetTypeParams. Setting a type parameter on more than one type
35 // will result in a panic.
36 //
37 // The constraint argument can be nil, and set later via SetConstraint. If the
38 // constraint is non-nil, it must be fully defined.
39 func NewTypeParam(obj *TypeName, constraint Type) *TypeParam {
40 return (*Checker)(nil).newTypeParam(obj, constraint)
41 }
42 43 // check may be nil
44 func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam {
45 // Always increment lastID, even if it is not used.
46 id := nextID()
47 if check != nil {
48 check.nextID++
49 id = check.nextID
50 }
51 typ := &TypeParam{check: check, id: id, obj: obj, index: -1, bound: constraint}
52 if obj.typ == nil {
53 obj.typ = typ
54 }
55 // iface may mutate typ.bound, so we must ensure that iface() is called
56 // at least once before the resulting TypeParam escapes.
57 if check != nil {
58 check.needsCleanup(typ)
59 } else if constraint != nil {
60 typ.iface()
61 }
62 return typ
63 }
64 65 // Obj returns the type name for the type parameter t.
66 func (t *TypeParam) Obj() *TypeName { return t.obj }
67 68 // Index returns the index of the type param within its param list, or -1 if
69 // the type parameter has not yet been bound to a type.
70 func (t *TypeParam) Index() int {
71 return t.index
72 }
73 74 // Constraint returns the type constraint specified for t.
75 func (t *TypeParam) Constraint() Type {
76 return t.bound
77 }
78 79 // SetConstraint sets the type constraint for t.
80 //
81 // It must be called by users of NewTypeParam after the bound's underlying is
82 // fully defined, and before using the type parameter in any way other than to
83 // form other types. Once SetConstraint returns the receiver, t is safe for
84 // concurrent use.
85 func (t *TypeParam) SetConstraint(bound Type) {
86 if bound == nil {
87 panic("nil constraint")
88 }
89 t.bound = bound
90 // iface may mutate t.bound (if bound is not an interface), so ensure that
91 // this is done before returning.
92 t.iface()
93 }
94 95 // Underlying returns the [underlying type] of the type parameter t, which is
96 // the underlying type of its constraint. This type is always an interface.
97 //
98 // [underlying type]: https://go.dev/ref/spec#Underlying_types.
99 func (t *TypeParam) Underlying() Type {
100 return t.iface()
101 }
102 103 func (t *TypeParam) String() string { return TypeString(t, nil) }
104 105 // ----------------------------------------------------------------------------
106 // Implementation
107 108 func (t *TypeParam) cleanup() {
109 t.iface()
110 t.check = nil
111 }
112 113 // iface returns the constraint interface of t.
114 func (t *TypeParam) iface() *Interface {
115 bound := t.bound
116 117 // determine constraint interface
118 var ityp *Interface
119 switch u := under(bound).(type) {
120 case *Basic:
121 if !isValid(u) {
122 // error is reported elsewhere
123 return &emptyInterface
124 }
125 case *Interface:
126 if isTypeParam(bound) {
127 // error is reported in Checker.collectTypeParams
128 return &emptyInterface
129 }
130 ityp = u
131 }
132 133 // If we don't have an interface, wrap constraint into an implicit interface.
134 if ityp == nil {
135 ityp = NewInterfaceType(nil, []Type{bound})
136 ityp.implicit = true
137 t.bound = ityp // update t.bound for next time (optimization)
138 }
139 140 // compute type set if necessary
141 if ityp.tset == nil {
142 // pos is used for tracing output; start with the type parameter position.
143 pos := t.obj.pos
144 // use the (original or possibly instantiated) type bound position if we have one
145 if n := asNamed(bound); n != nil {
146 pos = n.obj.pos
147 }
148 computeInterfaceTypeSet(t.check, pos, ityp)
149 }
150 151 return ityp
152 }
153 154 // is calls f with the specific type terms of t's constraint and reports whether
155 // all calls to f returned true. If there are no specific terms, is
156 // returns the result of f(nil).
157 func (t *TypeParam) is(f func(*term) bool) bool {
158 return t.iface().typeSet().is(f)
159 }
160 161 // typeset is an iterator over the (type/underlying type) pairs of the
162 // specific type terms of t's constraint.
163 // If there are no specific terms, typeset calls yield with (nil, nil).
164 // In any case, typeset is guaranteed to call yield at least once.
165 func (t *TypeParam) typeset(yield func(t, u Type) bool) {
166 t.iface().typeSet().typeset(yield)
167 }
168