...
Run Format

Source file src/go/types/conversions.go

Documentation: go/types

     1  // Copyright 2012 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  // This file implements typechecking of conversions.
     6  
     7  package types
     8  
     9  import "go/constant"
    10  
    11  // Conversion type-checks the conversion T(x).
    12  // The result is in x.
    13  func (check *Checker) conversion(x *operand, T Type) {
    14  	constArg := x.mode == constant_
    15  
    16  	var ok bool
    17  	switch {
    18  	case constArg && isConstType(T):
    19  		// constant conversion
    20  		switch t := T.Underlying().(*Basic); {
    21  		case representableConst(x.val, check.conf, t, &x.val):
    22  			ok = true
    23  		case isInteger(x.typ) && isString(t):
    24  			codepoint := int64(-1)
    25  			if i, ok := constant.Int64Val(x.val); ok {
    26  				codepoint = i
    27  			}
    28  			// If codepoint < 0 the absolute value is too large (or unknown) for
    29  			// conversion. This is the same as converting any other out-of-range
    30  			// value - let string(codepoint) do the work.
    31  			x.val = constant.MakeString(string(codepoint))
    32  			ok = true
    33  		}
    34  	case x.convertibleTo(check.conf, T):
    35  		// non-constant conversion
    36  		x.mode = value
    37  		ok = true
    38  	}
    39  
    40  	if !ok {
    41  		check.errorf(x.pos(), "cannot convert %s to %s", x, T)
    42  		x.mode = invalid
    43  		return
    44  	}
    45  
    46  	// The conversion argument types are final. For untyped values the
    47  	// conversion provides the type, per the spec: "A constant may be
    48  	// given a type explicitly by a constant declaration or conversion,...".
    49  	if isUntyped(x.typ) {
    50  		final := T
    51  		// - For conversions to interfaces, use the argument's default type.
    52  		// - For conversions of untyped constants to non-constant types, also
    53  		//   use the default type (e.g., []byte("foo") should report string
    54  		//   not []byte as type for the constant "foo").
    55  		// - Keep untyped nil for untyped nil arguments.
    56  		// - For integer to string conversions, keep the argument type.
    57  		//   (See also the TODO below.)
    58  		if IsInterface(T) || constArg && !isConstType(T) {
    59  			final = Default(x.typ)
    60  		} else if isInteger(x.typ) && isString(T) {
    61  			final = x.typ
    62  		}
    63  		check.updateExprType(x.expr, final, true)
    64  	}
    65  
    66  	x.typ = T
    67  }
    68  
    69  // TODO(gri) convertibleTo checks if T(x) is valid. It assumes that the type
    70  // of x is fully known, but that's not the case for say string(1<<s + 1.0):
    71  // Here, the type of 1<<s + 1.0 will be UntypedFloat which will lead to the
    72  // (correct!) refusal of the conversion. But the reported error is essentially
    73  // "cannot convert untyped float value to string", yet the correct error (per
    74  // the spec) is that we cannot shift a floating-point value: 1 in 1<<s should
    75  // be converted to UntypedFloat because of the addition of 1.0. Fixing this
    76  // is tricky because we'd have to run updateExprType on the argument first.
    77  // (Issue #21982.)
    78  
    79  func (x *operand) convertibleTo(conf *Config, T Type) bool {
    80  	// "x is assignable to T"
    81  	if x.assignableTo(conf, T, nil) {
    82  		return true
    83  	}
    84  
    85  	// "x's type and T have identical underlying types if tags are ignored"
    86  	V := x.typ
    87  	Vu := V.Underlying()
    88  	Tu := T.Underlying()
    89  	if IdenticalIgnoreTags(Vu, Tu) {
    90  		return true
    91  	}
    92  
    93  	// "x's type and T are unnamed pointer types and their pointer base types
    94  	// have identical underlying types if tags are ignored"
    95  	if V, ok := V.(*Pointer); ok {
    96  		if T, ok := T.(*Pointer); ok {
    97  			if IdenticalIgnoreTags(V.base.Underlying(), T.base.Underlying()) {
    98  				return true
    99  			}
   100  		}
   101  	}
   102  
   103  	// "x's type and T are both integer or floating point types"
   104  	if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
   105  		return true
   106  	}
   107  
   108  	// "x's type and T are both complex types"
   109  	if isComplex(V) && isComplex(T) {
   110  		return true
   111  	}
   112  
   113  	// "x is an integer or a slice of bytes or runes and T is a string type"
   114  	if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) {
   115  		return true
   116  	}
   117  
   118  	// "x is a string and T is a slice of bytes or runes"
   119  	if isString(V) && isBytesOrRunes(Tu) {
   120  		return true
   121  	}
   122  
   123  	// package unsafe:
   124  	// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
   125  	if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) {
   126  		return true
   127  	}
   128  	// "and vice versa"
   129  	if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) {
   130  		return true
   131  	}
   132  
   133  	return false
   134  }
   135  
   136  func isUintptr(typ Type) bool {
   137  	t, ok := typ.Underlying().(*Basic)
   138  	return ok && t.kind == Uintptr
   139  }
   140  
   141  func isUnsafePointer(typ Type) bool {
   142  	// TODO(gri): Is this (typ.Underlying() instead of just typ) correct?
   143  	//            The spec does not say so, but gc claims it is. See also
   144  	//            issue 6326.
   145  	t, ok := typ.Underlying().(*Basic)
   146  	return ok && t.kind == UnsafePointer
   147  }
   148  
   149  func isPointer(typ Type) bool {
   150  	_, ok := typ.Underlying().(*Pointer)
   151  	return ok
   152  }
   153  
   154  func isBytesOrRunes(typ Type) bool {
   155  	if s, ok := typ.(*Slice); ok {
   156  		t, ok := s.elem.Underlying().(*Basic)
   157  		return ok && (t.kind == Byte || t.kind == Rune)
   158  	}
   159  	return false
   160  }
   161  

View as plain text