]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: implement constant string(x) conversions
authorRobert Griesemer <gri@golang.org>
Thu, 7 Mar 2013 00:15:04 +0000 (16:15 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 7 Mar 2013 00:15:04 +0000 (16:15 -0800)
Fixes #4982.

R=adonovan, r
CC=golang-dev
https://golang.org/cl/7537043

src/pkg/go/types/conversions.go
src/pkg/go/types/operand.go
src/pkg/go/types/testdata/conversions.src

index fcbaf7717eb626cb2404b7d423ca0d24e63cd21f..ea629b961c16dc5526744a5055336d74d40aa61f 100644 (file)
@@ -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 {
index 982ffef8d8627cbeef7e707a67ddbda388f6453e..0e4ee2506a9b7fe6cad80c5033bed5e5a83da804 100644 (file)
@@ -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) ||
index 1b1518366f34d09ce6a90f8093ba21c05923aa29..291fa781e6a154c81973f3d54e34f815c025509d 100644 (file)
@@ -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