Source file src/go/types/typeparam.go

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

View as plain text