mirror of
https://github.com/golang/go
synced 2024-11-12 08:20:22 -07:00
go/types: implement constant string(x) conversions
Fixes #4982. R=adonovan, r CC=golang-dev https://golang.org/cl/7537043
This commit is contained in:
parent
b8db56ad2e
commit
0b2caf2717
@ -30,12 +30,32 @@ func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type, iota
|
||||
|
||||
if x.mode == constant && isConstType(typ) {
|
||||
// constant conversion
|
||||
// TODO(gri) implement this
|
||||
typ := underlying(typ).(*Basic)
|
||||
// For now just implement string(x) where x is an integer,
|
||||
// as a temporary work-around for issue 4982, which is a
|
||||
// common issue.
|
||||
if typ.Kind == String {
|
||||
switch {
|
||||
case x.isInteger(check.ctxt):
|
||||
codepoint, ok := x.val.(int64)
|
||||
if !ok {
|
||||
// absolute value too large (or unknown) for conversion;
|
||||
// same as converting any other out-of-range value - let
|
||||
// string(codepoint) do the work
|
||||
codepoint = -1
|
||||
}
|
||||
x.val = string(codepoint)
|
||||
case isString(x.typ):
|
||||
// nothing to do
|
||||
default:
|
||||
goto ErrorMsg
|
||||
}
|
||||
}
|
||||
// TODO(gri) verify the remaining conversions.
|
||||
} else {
|
||||
// non-constant conversion
|
||||
if !x.isConvertible(check.ctxt, typ) {
|
||||
check.invalidOp(conv.Pos(), "cannot convert %s to %s", x, typ)
|
||||
goto Error
|
||||
goto ErrorMsg
|
||||
}
|
||||
x.mode = value
|
||||
}
|
||||
@ -45,8 +65,11 @@ func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type, iota
|
||||
x.typ = typ
|
||||
return
|
||||
|
||||
ErrorMsg:
|
||||
check.invalidOp(conv.Pos(), "cannot convert %s to %s", x, typ)
|
||||
Error:
|
||||
x.mode = invalid
|
||||
x.expr = conv
|
||||
}
|
||||
|
||||
func (x *operand) isConvertible(ctxt *Context, T Type) bool {
|
||||
|
@ -205,6 +205,7 @@ func (x *operand) isAssignable(ctxt *Context, T Type) bool {
|
||||
}
|
||||
|
||||
// isInteger reports whether x is a (typed or untyped) integer value.
|
||||
// TODO(gri) remove ctxt argument - it is not required for UntypedInt.
|
||||
func (x *operand) isInteger(ctxt *Context) bool {
|
||||
return x.mode == invalid ||
|
||||
isInteger(x.typ) ||
|
||||
|
24
src/pkg/go/types/testdata/conversions.src
vendored
24
src/pkg/go/types/testdata/conversions.src
vendored
@ -8,11 +8,29 @@ package conversions
|
||||
|
||||
// argument count
|
||||
var (
|
||||
_v0 = int /* ERROR "one argument" */ ()
|
||||
_v1 = int /* ERROR "one argument" */ (1, 2)
|
||||
_ = int /* ERROR "one argument" */ ()
|
||||
_ = int /* ERROR "one argument" */ (1, 2)
|
||||
)
|
||||
|
||||
func string_conversions() {
|
||||
const A = string(65)
|
||||
assert(A == "A")
|
||||
const E = string(-1)
|
||||
assert(E == "\uFFFD")
|
||||
assert(E == string(1234567890))
|
||||
|
||||
type myint int
|
||||
assert(A == string(myint(65)))
|
||||
|
||||
type mystring string
|
||||
const _ mystring = mystring("foo")
|
||||
|
||||
const _ = string /* ERROR "cannot convert" */ (true)
|
||||
const _ = string /* ERROR "cannot convert" */ (1.2)
|
||||
const _ = string /* ERROR "cannot convert" */ (nil)
|
||||
}
|
||||
|
||||
//
|
||||
var (
|
||||
_v2 = int8(0)
|
||||
_ = int8(0)
|
||||
)
|
Loading…
Reference in New Issue
Block a user