under.go raw

   1  // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
   2  // Source: ../../cmd/compile/internal/types2/under.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  // under returns the true expanded underlying type.
  11  // If it doesn't exist, the result is Typ[Invalid].
  12  // under must only be called when a type is known
  13  // to be fully set up.
  14  func under(t Type) Type {
  15  	if t := asNamed(t); t != nil {
  16  		return t.under()
  17  	}
  18  	return t.Underlying()
  19  }
  20  
  21  // If typ is a type parameter, underIs returns the result of typ.underIs(f).
  22  // Otherwise, underIs returns the result of f(under(typ)).
  23  func underIs(typ Type, f func(Type) bool) bool {
  24  	var ok bool
  25  	typeset(typ, func(_, u Type) bool {
  26  		ok = f(u)
  27  		return ok
  28  	})
  29  	return ok
  30  }
  31  
  32  // typeset is an iterator over the (type/underlying type) pairs of the
  33  // specific type terms of the type set implied by t.
  34  // If t is a type parameter, the implied type set is the type set of t's constraint.
  35  // In that case, if there are no specific terms, typeset calls yield with (nil, nil).
  36  // If t is not a type parameter, the implied type set consists of just t.
  37  // In any case, typeset is guaranteed to call yield at least once.
  38  func typeset(t Type, yield func(t, u Type) bool) {
  39  	if p, _ := Unalias(t).(*TypeParam); p != nil {
  40  		p.typeset(yield)
  41  		return
  42  	}
  43  	yield(t, under(t))
  44  }
  45  
  46  // A typeError describes a type error.
  47  type typeError struct {
  48  	format_ string
  49  	args    []any
  50  }
  51  
  52  var emptyTypeError typeError
  53  
  54  func typeErrorf(format string, args ...any) *typeError {
  55  	if format == "" {
  56  		return &emptyTypeError
  57  	}
  58  	return &typeError{format, args}
  59  }
  60  
  61  // format formats a type error as a string.
  62  // check may be nil.
  63  func (err *typeError) format(check *Checker) string {
  64  	return check.sprintf(err.format_, err.args...)
  65  }
  66  
  67  // If t is a type parameter, cond is nil, and t's type set contains no channel types,
  68  // commonUnder returns the common underlying type of all types in t's type set if
  69  // it exists, or nil and a type error otherwise.
  70  //
  71  // If t is a type parameter, cond is nil, and there are channel types, t's type set
  72  // must only contain channel types, they must all have the same element types,
  73  // channel directions must not conflict, and commonUnder returns one of the most
  74  // restricted channels. Otherwise, the function returns nil and a type error.
  75  //
  76  // If cond != nil, each pair (t, u) of type and underlying type in t's type set
  77  // must satisfy the condition expressed by cond. If the result of cond is != nil,
  78  // commonUnder returns nil and the type error reported by cond.
  79  // Note that cond is called before any other conditions are checked; specifically
  80  // cond may be called with (nil, nil) if the type set contains no specific types.
  81  //
  82  // If t is not a type parameter, commonUnder behaves as if t was a type parameter
  83  // with the single type t in its type set.
  84  func commonUnder(t Type, cond func(t, u Type) *typeError) (Type, *typeError) {
  85  	var ct, cu Type // type and respective common underlying type
  86  	var err *typeError
  87  
  88  	bad := func(format string, args ...any) bool {
  89  		err = typeErrorf(format, args...)
  90  		return false
  91  	}
  92  
  93  	typeset(t, func(t, u Type) bool {
  94  		if cond != nil {
  95  			if err = cond(t, u); err != nil {
  96  				return false
  97  			}
  98  		}
  99  
 100  		if u == nil {
 101  			return bad("no specific type")
 102  		}
 103  
 104  		// If this is the first type we're seeing, we're done.
 105  		if cu == nil {
 106  			ct, cu = t, u
 107  			return true
 108  		}
 109  
 110  		// If we've seen a channel before, and we have a channel now, they must be compatible.
 111  		if chu, _ := cu.(*Chan); chu != nil {
 112  			if ch, _ := u.(*Chan); ch != nil {
 113  				if !Identical(chu.elem, ch.elem) {
 114  					return bad("channels %s and %s have different element types", ct, t)
 115  				}
 116  				// If we have different channel directions, keep the restricted one
 117  				// and complain if they conflict.
 118  				switch {
 119  				case chu.dir == ch.dir:
 120  					// nothing to do
 121  				case chu.dir == SendRecv:
 122  					ct, cu = t, u // switch to restricted channel
 123  				case ch.dir != SendRecv:
 124  					return bad("channels %s and %s have conflicting directions", ct, t)
 125  				}
 126  				return true
 127  			}
 128  		}
 129  
 130  		// Otherwise, the current type must have the same underlying type as all previous types.
 131  		if !Identical(cu, u) {
 132  			return bad("%s and %s have different underlying types", ct, t)
 133  		}
 134  
 135  		return true
 136  	})
 137  
 138  	if err != nil {
 139  		return nil, err
 140  	}
 141  	return cu, nil
 142  }
 143