Source file src/go/types/under.go

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

View as plain text