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