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  

View as plain text