aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2013-03-06 16:15:04 -0800
committerRobert Griesemer <gri@golang.org>2013-03-06 16:15:04 -0800
commit0b2caf27177e47b587df6ef4dce2df67ad3e4666 (patch)
tree352a3de96aa5cd094b67c4b4eae075b0d4125448 /src
parentb8db56ad2e91f984eef4e08b85fefcd088f2def9 (diff)
downloadgo-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.go29
-rw-r--r--src/pkg/go/types/operand.go1
-rw-r--r--src/pkg/go/types/testdata/conversions.src26
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