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

View as plain text