Source file src/cmd/compile/internal/types2/under.go

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package types2
     6  
     7  // under returns the true expanded underlying type.
     8  // If it doesn't exist, the result is Typ[Invalid].
     9  // under must only be called when a type is known
    10  // to be fully set up.
    11  func under(t Type) Type {
    12  	if t := asNamed(t); t != nil {
    13  		return t.under()
    14  	}
    15  	return t.Underlying()
    16  }
    17  
    18  // If t is not a type parameter, coreType returns the underlying type.
    19  // If t is a type parameter, coreType returns the single underlying
    20  // type of all types in its type set if it exists, or nil otherwise. If the
    21  // type set contains only unrestricted and restricted channel types (with
    22  // identical element types), the single underlying type is the restricted
    23  // channel type if the restrictions are always the same, or nil otherwise.
    24  func coreType(t Type) Type {
    25  	t = Unalias(t)
    26  	tpar, _ := t.(*TypeParam)
    27  	if tpar == nil {
    28  		return under(t)
    29  	}
    30  
    31  	var su Type
    32  	if tpar.underIs(func(u Type) bool {
    33  		if u == nil {
    34  			return false
    35  		}
    36  		if su != nil {
    37  			u = match(su, u)
    38  			if u == nil {
    39  				return false
    40  			}
    41  		}
    42  		// su == nil || match(su, u) != nil
    43  		su = u
    44  		return true
    45  	}) {
    46  		return su
    47  	}
    48  	return nil
    49  }
    50  
    51  // coreString is like coreType but also considers []byte
    52  // and strings as identical. In this case, if successful and we saw
    53  // a string, the result is of type (possibly untyped) string.
    54  func coreString(t Type) Type {
    55  	t = Unalias(t)
    56  	tpar, _ := t.(*TypeParam)
    57  	if tpar == nil {
    58  		return under(t) // string or untyped string
    59  	}
    60  
    61  	var su Type
    62  	hasString := false
    63  	if tpar.underIs(func(u Type) bool {
    64  		if u == nil {
    65  			return false
    66  		}
    67  		if isString(u) {
    68  			u = NewSlice(universeByte)
    69  			hasString = true
    70  		}
    71  		if su != nil {
    72  			u = match(su, u)
    73  			if u == nil {
    74  				return false
    75  			}
    76  		}
    77  		// su == nil || match(su, u) != nil
    78  		su = u
    79  		return true
    80  	}) {
    81  		if hasString {
    82  			return Typ[String]
    83  		}
    84  		return su
    85  	}
    86  	return nil
    87  }
    88  
    89  // If x and y are identical, match returns x.
    90  // If x and y are identical channels but for their direction
    91  // and one of them is unrestricted, match returns the channel
    92  // with the restricted direction.
    93  // In all other cases, match returns nil.
    94  func match(x, y Type) Type {
    95  	// Common case: we don't have channels.
    96  	if Identical(x, y) {
    97  		return x
    98  	}
    99  
   100  	// We may have channels that differ in direction only.
   101  	if x, _ := x.(*Chan); x != nil {
   102  		if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) {
   103  			// We have channels that differ in direction only.
   104  			// If there's an unrestricted channel, select the restricted one.
   105  			switch {
   106  			case x.dir == SendRecv:
   107  				return y
   108  			case y.dir == SendRecv:
   109  				return x
   110  			}
   111  		}
   112  	}
   113  
   114  	// types are different
   115  	return nil
   116  }
   117  

View as plain text