typeparam.go raw

   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