// Conversion type-checks the conversion T(x). // The result is in x. func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ var ok bool switch { case constArg && isConstType(T): // constant conversion switch t := T.Underlying().(*Basic); { case representableConst(x.val, check.conf, t, &x.val): ok = true case isInteger(x.typ) && isString(t): codepoint := int64(-1) if i, ok := constant.Int64Val(x.val); ok { codepoint = i } // If codepoint < 0 the absolute value is too large (or unknown) for // conversion. This is the same as converting any other out-of-range // value - let string(codepoint) do the work. x.val = constant.MakeString(string(codepoint)) ok = true } case x.convertibleTo(check.conf, T): // non-constant conversion x.mode = value ok = true } if !ok { check.errorf(x.pos(), "cannot convert %s to %s", x, T) x.mode = invalid return } // The conversion argument types are final. For untyped values the // conversion provides the type, per the spec: "A constant may be // given a type explicitly by a constant declaration or conversion,...". final := x.typ if isUntyped(x.typ) { final = T // - For conversions to interfaces, use the argument's default type. // - For conversions of untyped constants to non-constant types, also // use the default type (e.g., []byte("foo") should report string // not []byte as type for the constant "foo"). // - Keep untyped nil for untyped nil arguments. if IsInterface(T) || constArg && !isConstType(T) { final = defaultType(x.typ) } check.updateExprType(x.expr, final, true) } x.typ = T }
func (c *converter) convertConstantValue(v goconstant.Value) constant.Value { if v == nil { return nil } if v, ok := c.converted[v]; ok { return v.(constant.Value) } var ret constant.Value switch v.Kind() { case goconstant.Bool: ret = constant.MakeBool(goconstant.BoolVal(v)) case goconstant.String: ret = constant.MakeString(goconstant.StringVal(v)) case goconstant.Int: ret = constant.MakeFromLiteral(v.String(), token.INT, 0) case goconstant.Float: ret = constant.MakeFromLiteral(v.String(), token.FLOAT, 0) case goconstant.Complex: ret = constant.MakeFromLiteral(v.String(), token.IMAG, 0) } c.converted[v] = ret return ret }