diff options
| author | Robert Griesemer <gri@golang.org> | 2013-03-06 16:15:04 -0800 |
|---|---|---|
| committer | Robert Griesemer <gri@golang.org> | 2013-03-06 16:15:04 -0800 |
| commit | 0b2caf27177e47b587df6ef4dce2df67ad3e4666 (patch) | |
| tree | 352a3de96aa5cd094b67c4b4eae075b0d4125448 /src | |
| parent | b8db56ad2e91f984eef4e08b85fefcd088f2def9 (diff) | |
| download | go-0b2caf27177e47b587df6ef4dce2df67ad3e4666.tar.xz | |
go/types: implement constant string(x) conversions
Fixes #4982.
R=adonovan, r
CC=golang-dev
https://golang.org/cl/7537043
Diffstat (limited to 'src')
| -rw-r--r-- | src/pkg/go/types/conversions.go | 29 | ||||
| -rw-r--r-- | src/pkg/go/types/operand.go | 1 | ||||
| -rw-r--r-- | src/pkg/go/types/testdata/conversions.src | 26 |
3 files changed, 49 insertions, 7 deletions
diff --git a/src/pkg/go/types/conversions.go b/src/pkg/go/types/conversions.go index fcbaf7717e..ea629b961c 100644 --- a/src/pkg/go/types/conversions.go +++ b/src/pkg/go/types/conversions.go @@ -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 { diff --git a/src/pkg/go/types/operand.go b/src/pkg/go/types/operand.go index 982ffef8d8..0e4ee2506a 100644 --- a/src/pkg/go/types/operand.go +++ b/src/pkg/go/types/operand.go @@ -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) || diff --git a/src/pkg/go/types/testdata/conversions.src b/src/pkg/go/types/testdata/conversions.src index 1b1518366f..291fa781e6 100644 --- a/src/pkg/go/types/testdata/conversions.src +++ b/src/pkg/go/types/testdata/conversions.src @@ -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) )
\ No newline at end of file |
