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

View as plain text