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.
5 // This file implements typechecking of conversions.
13 // conversion typechecks the type conversion conv to type typ. iota is the current
14 // value of iota or -1 if iota doesn't have a value in the current context. The result
15 // of the conversion is returned via x. If the conversion has type errors, the returned
16 // x is marked as invalid (x.mode == invalid).
18 func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type, iota int) {
19 // all conversions have one argument
20 if len(conv.Args) != 1 {
21 check.invalidOp(conv.Pos(), "%s conversion requires exactly one argument", conv)
26 check.expr(x, conv.Args[0], nil, iota)
27 if x.mode == invalid {
31 if x.mode == constant && isConstType(typ) {
32 // constant conversion
33 // TODO(gri) implement this
35 // non-constant conversion
36 if !x.isConvertible(typ) {
37 check.invalidOp(conv.Pos(), "cannot convert %s to %s", x, typ)
51 func (x *operand) isConvertible(T Type) bool {
52 // "x is assignable to T"
53 if x.isAssignable(T) {
57 // "x's type and T have identical underlying types"
61 if IsIdentical(Vu, Tu) {
65 // "x's type and T are unnamed pointer types and their pointer base types have identical underlying types"
66 if V, ok := V.(*Pointer); ok {
67 if T, ok := T.(*Pointer); ok {
68 if IsIdentical(underlying(V.Base), underlying(T.Base)) {
74 // "x's type and T are both integer or floating point types"
75 if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
79 // "x's type and T are both complex types"
80 if isComplex(V) && isComplex(T) {
84 // "x is an integer or a slice of bytes or runes and T is a string type"
85 if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) {
89 // "x is a string and T is a slice of bytes or runes"
90 if isString(V) && isBytesOrRunes(Tu) {
95 // "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
96 if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) {
100 if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) {
107 func isUintptr(typ Type) bool {
108 t, ok := typ.(*Basic)
109 return ok && t.Kind == Uintptr
112 func isUnsafePointer(typ Type) bool {
113 t, ok := typ.(*Basic)
114 return ok && t.Kind == UnsafePointer
117 func isPointer(typ Type) bool {
118 _, ok := typ.(*Pointer)
122 func isBytesOrRunes(typ Type) bool {
123 if s, ok := typ.(*Slice); ok {
124 t, ok := underlying(s.Elt).(*Basic)
125 return ok && (t.Kind == Byte || t.Kind == Rune)