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  // 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  

View as plain text