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  // If t is not a type parameter, coreType returns the underlying type.
    47  // If t is a type parameter, coreType returns the single underlying
    48  // type of all types in its type set if it exists, or nil otherwise. If the
    49  // type set contains only unrestricted and restricted channel types (with
    50  // identical element types), the single underlying type is the restricted
    51  // channel type if the restrictions are always the same, or nil otherwise.
    52  func coreType(t Type) Type {
    53  	var su Type
    54  	typeset(t, func(_, u Type) bool {
    55  		if u == nil {
    56  			return false
    57  		}
    58  		if su != nil {
    59  			u = match(su, u)
    60  			if u == nil {
    61  				su = nil
    62  				return false
    63  			}
    64  		}
    65  		// su == nil || match(su, u) != nil
    66  		su = u
    67  		return true
    68  	})
    69  	return su
    70  }
    71  
    72  // coreString is like coreType but also considers []byte
    73  // and strings as identical. In this case, if successful and we saw
    74  // a string, the result is of type (possibly untyped) string.
    75  func coreString(t Type) Type {
    76  	// This explicit case is needed because otherwise the
    77  	// result would be string if t is an untyped string.
    78  	if !isTypeParam(t) {
    79  		return under(t) // untyped string remains untyped
    80  	}
    81  
    82  	var su Type
    83  	hasString := false
    84  	typeset(t, func(_, u Type) bool {
    85  		if u == nil {
    86  			return false
    87  		}
    88  		if isString(u) {
    89  			u = NewSlice(universeByte)
    90  			hasString = true
    91  		}
    92  		if su != nil {
    93  			u = match(su, u)
    94  			if u == nil {
    95  				su = nil
    96  				hasString = false
    97  				return false
    98  			}
    99  		}
   100  		// su == nil || match(su, u) != nil
   101  		su = u
   102  		return true
   103  	})
   104  	if hasString {
   105  		return Typ[String]
   106  	}
   107  	return su
   108  }
   109  
   110  // If x and y are identical, match returns x.
   111  // If x and y are identical channels but for their direction
   112  // and one of them is unrestricted, match returns the channel
   113  // with the restricted direction.
   114  // In all other cases, match returns nil.
   115  func match(x, y Type) Type {
   116  	// Common case: we don't have channels.
   117  	if Identical(x, y) {
   118  		return x
   119  	}
   120  
   121  	// We may have channels that differ in direction only.
   122  	if x, _ := x.(*Chan); x != nil {
   123  		if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) {
   124  			// We have channels that differ in direction only.
   125  			// If there's an unrestricted channel, select the restricted one.
   126  			switch {
   127  			case x.dir == SendRecv:
   128  				return y
   129  			case y.dir == SendRecv:
   130  				return x
   131  			}
   132  		}
   133  	}
   134  
   135  	// types are different
   136  	return nil
   137  }
   138  

View as plain text