From d13d94afe78f847f81a504071dafdb378cea6438 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 12 Aug 2013 14:57:08 -0700 Subject: [PATCH] go.tools/go/types: do rounding in constant numeric conversions - cleaned up surrounding code - adjusted error message positions for too few/many argument errors - added more conversion tests - added all tests under test/ken to std tests R=adonovan, r TBR=adonovan CC=golang-dev https://golang.org/cl/12711043 --- go/types/api.go | 1 - go/types/call.go | 22 ++++- go/types/conversions.go | 96 +++++++------------ go/types/expr.go | 96 ++++++++++++++++--- go/types/operand.go | 4 +- go/types/stdlib_test.go | 7 +- go/types/testdata/const1.src | 151 ++++++++++++++++++++++++++---- go/types/testdata/conversions.src | 29 +++--- go/types/testdata/expr3.src | 10 +- go/types/testdata/stmt0.src | 2 +- 10 files changed, 293 insertions(+), 125 deletions(-) diff --git a/go/types/api.go b/go/types/api.go index 1b132def..5f6a0ab8 100644 --- a/go/types/api.go +++ b/go/types/api.go @@ -173,7 +173,6 @@ func IsAssignableTo(V, T Type) bool { return x.isAssignableTo(nil, T) // config not needed for non-constant x } -// BUG(gri): Conversions of constants only change the type, not the value (e.g., int(1.1) is wrong). // BUG(gri): Some built-ins don't check parameters fully, yet (e.g. append). // BUG(gri): Use of labels is only partially checked. // BUG(gri): Unused variables and imports are not reported. diff --git a/go/types/call.go b/go/types/call.go index 6c4e102f..b863ebb3 100644 --- a/go/types/call.go +++ b/go/types/call.go @@ -26,13 +26,29 @@ func (check *checker) call(x *operand, e *ast.CallExpr) { } if x.mode == typexpr { - check.conversion(x, e, x.typ) + // conversion + T := x.typ + x.mode = invalid + switch n := len(e.Args); n { + case 0: + check.errorf(e.Rparen, "missing argument in conversion to %s", T) + case 1: + check.expr(x, e.Args[0]) + if x.mode != invalid { + check.conversion(x, T) + if x.mode != invalid { + check.conversions[e] = true // for cap/len checking + } + } + default: + check.errorf(e.Args[n-1].Pos(), "too many arguments in conversion to %s", T) + } + x.expr = e return } if sig, ok := x.typ.Underlying().(*Signature); ok { // function/method call - passSlice := false if e.Ellipsis.IsValid() { // last argument is of the form x... @@ -84,7 +100,7 @@ func (check *checker) call(x *operand, e *ast.CallExpr) { n++ } if n < sig.params.Len() { - check.errorf(e.Fun.Pos(), "too few arguments in call to %s", e.Fun) + check.errorf(e.Rparen, "too few arguments in call to %s", e.Fun) // ok to continue } diff --git a/go/types/conversions.go b/go/types/conversions.go index 8e1f32bc..3645ee17 100644 --- a/go/types/conversions.go +++ b/go/types/conversions.go @@ -6,89 +6,57 @@ package types -import ( - "go/ast" +import "code.google.com/p/go.tools/go/exact" - "code.google.com/p/go.tools/go/exact" -) - -// conversion typechecks the type conversion conv to type typ. -// The result of the conversion is returned via x. -// If the conversion has type errors, the returned -// x is marked as invalid (x.mode == invalid). -// -func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type) { - var final Type // declare before gotos - - // all conversions have one argument - if len(conv.Args) != 1 { - check.invalidOp(conv.Pos(), "%s conversion requires exactly one argument", conv) - goto Error - } - - // evaluate argument - check.expr(x, conv.Args[0]) - if x.mode == invalid { - goto Error - } - - if x.mode == constant && isConstType(typ) { +// Conversion type-checks the conversion T(x). +// The result is in x. +func (check *checker) conversion(x *operand, T Type) { + switch { + case x.mode == constant && isConstType(T): // constant conversion - typ := typ.Underlying().(*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(): - codepoint := int64(-1) - if i, ok := exact.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 = exact.MakeString(string(codepoint)) - case isString(x.typ): - // nothing to do - default: - goto ErrorMsg + switch t := T.Underlying().(*Basic); { + case isRepresentableConst(x.val, check.conf, t.kind, &x.val): + // nothing to do + case x.isInteger() && isString(t): + codepoint := int64(-1) + if i, ok := exact.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 = exact.MakeString(string(codepoint)) + default: + x.mode = invalid } - // TODO(gri) verify the remaining conversions. - } else { + case x.isConvertible(check.conf, T): // non-constant conversion - if !x.isConvertible(check.conf, typ) { - goto ErrorMsg - } x.mode = value + default: + x.mode = invalid + } + + if x.mode == invalid { + check.errorf(x.pos(), "cannot convert %s to %s", x, T) + 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 + final := x.typ if isUntyped(final) { - final = typ + final = T // For conversions to interfaces, use the argument type's // default type instead. Keep untyped nil for untyped nil // arguments. - if _, ok := typ.Underlying().(*Interface); ok { + if _, ok := T.Underlying().(*Interface); ok { final = defaultType(x.typ) } } + + x.typ = T check.updateExprType(x.expr, final, true) - - check.conversions[conv] = true // for cap/len checking - x.expr = conv - 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(conf *Config, T Type) bool { diff --git a/go/types/expr.go b/go/types/expr.go index 6ef878fe..c4478585 100644 --- a/go/types/expr.go +++ b/go/types/expr.go @@ -158,18 +158,46 @@ func isComparison(op token.Token) bool { func fitsFloat32(x exact.Value) bool { f, _ := exact.Float64Val(x) - // We assume that float32(f) returns an Inf if f - // cannot be represented as a float32, or if f - // is an Inf. This is not supported by the spec. + // spec: "In all non-constant conversions involving floating-point + // or complex values, if the result type cannot represent the value + // the conversion succeeds but the result value is implementation- + // dependent." + // + // We assume that float32(f) returns an Inf if f cannot be represented + // as a float32, or if f is an Inf. return !math.IsInf(float64(float32(f)), 0) } +func roundFloat32(x exact.Value) exact.Value { + f, _ := exact.Float64Val(x) + f = float64(float32(f)) + if !math.IsInf(f, 0) { + return exact.MakeFloat64(f) + } + return nil +} + func fitsFloat64(x exact.Value) bool { f, _ := exact.Float64Val(x) return !math.IsInf(f, 0) } -func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool { +func roundFloat64(x exact.Value) exact.Value { + f, _ := exact.Float64Val(x) + if !math.IsInf(f, 0) { + return exact.MakeFloat64(f) + } + return nil +} + +// isRepresentableConst reports whether x can be represented as +// value of the given basic type kind and for the configuration +// provided (only needed for int/uint sizes). +// +// If rounded != nil, *rounded is set to the rounded value of x for +// representable floating-point values; it is left alone otherwise. +// It is ok to provide the addressof the first argument for rounded. +func isRepresentableConst(x exact.Value, conf *Config, as BasicKind, rounded *exact.Value) bool { switch x.Kind() { case exact.Unknown: return true @@ -224,9 +252,23 @@ func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool { case Uint64: return exact.Sign(x) >= 0 && n <= 64 case Float32, Complex64: - return fitsFloat32(x) + if rounded == nil { + return fitsFloat32(x) + } + r := roundFloat32(x) + if r != nil { + *rounded = r + return true + } case Float64, Complex128: - return fitsFloat64(x) + if rounded == nil { + return fitsFloat64(x) + } + r := roundFloat64(x) + if r != nil { + *rounded = r + return true + } case UntypedInt, UntypedFloat, UntypedComplex: return true } @@ -234,9 +276,23 @@ func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool { case exact.Float: switch as { case Float32, Complex64: - return fitsFloat32(x) + if rounded == nil { + return fitsFloat32(x) + } + r := roundFloat32(x) + if r != nil { + *rounded = r + return true + } case Float64, Complex128: - return fitsFloat64(x) + if rounded == nil { + return fitsFloat64(x) + } + r := roundFloat64(x) + if r != nil { + *rounded = r + return true + } case UntypedFloat, UntypedComplex: return true } @@ -244,9 +300,25 @@ func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool { case exact.Complex: switch as { case Complex64: - return fitsFloat32(exact.Real(x)) && fitsFloat32(exact.Imag(x)) + if rounded == nil { + return fitsFloat32(exact.Real(x)) && fitsFloat32(exact.Imag(x)) + } + re := roundFloat32(exact.Real(x)) + im := roundFloat32(exact.Imag(x)) + if re != nil && im != nil { + *rounded = exact.BinaryOp(re, token.ADD, exact.MakeImag(im)) + return true + } case Complex128: - return fitsFloat64(exact.Real(x)) && fitsFloat64(exact.Imag(x)) + if rounded == nil { + return fitsFloat64(exact.Real(x)) && fitsFloat64(exact.Imag(x)) + } + re := roundFloat64(exact.Real(x)) + im := roundFloat64(exact.Imag(x)) + if re != nil && im != nil { + *rounded = exact.BinaryOp(re, token.ADD, exact.MakeImag(im)) + return true + } case UntypedComplex: return true } @@ -270,7 +342,7 @@ func (check *checker) isRepresentable(x *operand, typ *Basic) { return } - if !isRepresentableConst(x.val, check.conf, typ.kind) { + if !isRepresentableConst(x.val, check.conf, typ.kind, &x.val) { var msg string if isNumeric(x.typ) && isNumeric(typ) { msg = "%s overflows (or cannot be accurately represented as) %s" @@ -512,7 +584,7 @@ func (check *checker) shift(x, y *operand, op token.Token) { // The lhs must be of integer type or be representable // as an integer; otherwise the shift has no chance. - if !isInteger(x.typ) && (!untypedx || !isRepresentableConst(x.val, nil, UntypedInt)) { + if !isInteger(x.typ) && (!untypedx || !isRepresentableConst(x.val, nil, UntypedInt, nil)) { check.invalidOp(x.pos(), "shifted operand %s must be integer", x) x.mode = invalid return diff --git a/go/types/operand.go b/go/types/operand.go index c08a7bc7..7c49abf5 100644 --- a/go/types/operand.go +++ b/go/types/operand.go @@ -184,7 +184,7 @@ func (x *operand) isAssignableTo(conf *Config, T Type) bool { switch t := Tu.(type) { case *Basic: if x.mode == constant { - return isRepresentableConst(x.val, conf, t.kind) + return isRepresentableConst(x.val, conf, t.kind, nil) } // The result of a comparison is an untyped boolean, // but may not be a constant. @@ -205,5 +205,5 @@ func (x *operand) isAssignableTo(conf *Config, T Type) bool { func (x *operand) isInteger() bool { return x.mode == invalid || isInteger(x.typ) || - x.mode == constant && isRepresentableConst(x.val, nil, UntypedInt) // no *Config required for UntypedInt + x.mode == constant && isRepresentableConst(x.val, nil, UntypedInt, nil) // no *Config required for UntypedInt } diff --git a/go/types/stdlib_test.go b/go/types/stdlib_test.go index 1ad6d3f7..d3978520 100644 --- a/go/types/stdlib_test.go +++ b/go/types/stdlib_test.go @@ -105,9 +105,10 @@ func TestStdtest(t *testing.T) { } func TestStdfixed(t *testing.T) { - testTestDir(t, filepath.Join(runtime.GOROOT(), "test/fixedbugs"), + testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"), "bug050.go", "bug088.go", "bug106.go", // TODO(gri) parser loses comments when bailing out early "bug222.go", "bug282.go", "bug306.go", // TODO(gri) parser loses comments when bailing out early + "issue4776.go", // TODO(gri) parser loses comments when bailing out early "bug136.go", "bug179.go", "bug344.go", // TODO(gri) implement missing label checks "bug251.go", // TODO(gri) incorrect cycle checks for interface types "bug165.go", // TODO(gri) isComparable not working for incomplete struct type @@ -123,6 +124,10 @@ func TestStdfixed(t *testing.T) { ) } +func TestStdken(t *testing.T) { + testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "ken")) +} + // Package paths of excluded packages. var excluded = map[string]bool{ "builtin": true, diff --git a/go/types/testdata/const1.src b/go/types/testdata/const1.src index 0232f452..a600fdc6 100644 --- a/go/types/testdata/const1.src +++ b/go/types/testdata/const1.src @@ -56,138 +56,249 @@ const ( maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52) ) -var ( +const ( _ int8 = minInt8 /* ERROR "overflows" */ - 1 _ int8 = minInt8 _ int8 = maxInt8 _ int8 = maxInt8 /* ERROR "overflows" */ + 1 _ int8 = smallestFloat64 /* ERROR "overflows" */ + + _ = int8(minInt8 /* ERROR "cannot convert" */ - 1) + _ = int8(minInt8) + _ = int8(maxInt8) + _ = int8(maxInt8 /* ERROR "cannot convert" */ + 1) + _ = int8(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ int16 = minInt16 /* ERROR "overflows" */ - 1 _ int16 = minInt16 _ int16 = maxInt16 _ int16 = maxInt16 /* ERROR "overflows" */ + 1 _ int16 = smallestFloat64 /* ERROR "overflows" */ + + _ = int16(minInt16 /* ERROR "cannot convert" */ - 1) + _ = int16(minInt16) + _ = int16(maxInt16) + _ = int16(maxInt16 /* ERROR "cannot convert" */ + 1) + _ = int16(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ int32 = minInt32 /* ERROR "overflows" */ - 1 _ int32 = minInt32 _ int32 = maxInt32 _ int32 = maxInt32 /* ERROR "overflows" */ + 1 _ int32 = smallestFloat64 /* ERROR "overflows" */ + + _ = int32(minInt32 /* ERROR "cannot convert" */ - 1) + _ = int32(minInt32) + _ = int32(maxInt32) + _ = int32(maxInt32 /* ERROR "cannot convert" */ + 1) + _ = int32(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ int64 = minInt64 /* ERROR "overflows" */ - 1 _ int64 = minInt64 _ int64 = maxInt64 _ int64 = maxInt64 /* ERROR "overflows" */ + 1 _ int64 = smallestFloat64 /* ERROR "overflows" */ + + _ = int64(minInt64 /* ERROR "cannot convert" */ - 1) + _ = int64(minInt64) + _ = int64(maxInt64) + _ = int64(maxInt64 /* ERROR "cannot convert" */ + 1) + _ = int64(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ int = minInt /* ERROR "overflows" */ - 1 _ int = minInt _ int = maxInt _ int = maxInt /* ERROR "overflows" */ + 1 _ int = smallestFloat64 /* ERROR "overflows" */ + + _ = int(minInt /* ERROR "cannot convert" */ - 1) + _ = int(minInt) + _ = int(maxInt) + _ = int(maxInt /* ERROR "cannot convert" */ + 1) + _ = int(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ uint8 = 0 /* ERROR "overflows" */ - 1 _ uint8 = 0 _ uint8 = maxUint8 _ uint8 = maxUint8 /* ERROR "overflows" */ + 1 _ uint8 = smallestFloat64 /* ERROR "overflows" */ + + _ = uint8(0 /* ERROR "cannot convert" */ - 1) + _ = uint8(0) + _ = uint8(maxUint8) + _ = uint8(maxUint8 /* ERROR "cannot convert" */ + 1) + _ = uint8(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ uint16 = 0 /* ERROR "overflows" */ - 1 _ uint16 = 0 _ uint16 = maxUint16 _ uint16 = maxUint16 /* ERROR "overflows" */ + 1 _ uint16 = smallestFloat64 /* ERROR "overflows" */ + + _ = uint16(0 /* ERROR "cannot convert" */ - 1) + _ = uint16(0) + _ = uint16(maxUint16) + _ = uint16(maxUint16 /* ERROR "cannot convert" */ + 1) + _ = uint16(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ uint32 = 0 /* ERROR "overflows" */ - 1 _ uint32 = 0 _ uint32 = maxUint32 _ uint32 = maxUint32 /* ERROR "overflows" */ + 1 _ uint32 = smallestFloat64 /* ERROR "overflows" */ + + _ = uint32(0 /* ERROR "cannot convert" */ - 1) + _ = uint32(0) + _ = uint32(maxUint32) + _ = uint32(maxUint32 /* ERROR "cannot convert" */ + 1) + _ = uint32(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ uint64 = 0 /* ERROR "overflows" */ - 1 _ uint64 = 0 _ uint64 = maxUint64 _ uint64 = maxUint64 /* ERROR "overflows" */ + 1 _ uint64 = smallestFloat64 /* ERROR "overflows" */ + + _ = uint64(0 /* ERROR "cannot convert" */ - 1) + _ = uint64(0) + _ = uint64(maxUint64) + _ = uint64(maxUint64 /* ERROR "cannot convert" */ + 1) + _ = uint64(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ uint = 0 /* ERROR "overflows" */ - 1 _ uint = 0 _ uint = maxUint _ uint = maxUint /* ERROR "overflows" */ + 1 _ uint = smallestFloat64 /* ERROR "overflows" */ + + _ = uint(0 /* ERROR "cannot convert" */ - 1) + _ = uint(0) + _ = uint(maxUint) + _ = uint(maxUint /* ERROR "cannot convert" */ + 1) + _ = uint(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ uintptr = 0 /* ERROR "overflows" */ - 1 _ uintptr = 0 _ uintptr = maxUintptr _ uintptr = maxUintptr /* ERROR "overflows" */ + 1 _ uintptr = smallestFloat64 /* ERROR "overflows" */ + + _ = uintptr(0 /* ERROR "cannot convert" */ - 1) + _ = uintptr(0) + _ = uintptr(maxUintptr) + _ = uintptr(maxUintptr /* ERROR "cannot convert" */ + 1) + _ = uintptr(smallestFloat64 /* ERROR "cannot convert" */) ) -var ( +const ( _ float32 = minInt64 _ float64 = minInt64 _ complex64 = minInt64 _ complex128 = minInt64 + + _ = float32(minInt64) + _ = float64(minInt64) + _ = complex64(minInt64) + _ = complex128(minInt64) ) -var ( +const ( _ float32 = maxUint64 _ float64 = maxUint64 _ complex64 = maxUint64 _ complex128 = maxUint64 + + _ = float32(maxUint64) + _ = float64(maxUint64) + _ = complex64(maxUint64) + _ = complex128(maxUint64) ) // TODO(gri) find smaller deltas below -const delta32 = maxFloat32 >> 23 +const delta32 = maxFloat32/(1 << 23) -var ( +const ( _ float32 = - /* ERROR "overflow" */ (maxFloat32 + delta32) _ float32 = -maxFloat32 _ float32 = maxFloat32 _ float32 = maxFloat32 /* ERROR "overflow" */ + delta32 + + _ = float32(- /* ERROR "cannot convert" */ (maxFloat32 + delta32)) + _ = float32(-maxFloat32) + _ = float32(maxFloat32) + _ = float32(maxFloat32 /* ERROR "cannot convert" */ + delta32) ) -const delta64 = maxFloat64 >> 52 +const delta64 = maxFloat64/(1 << 52) -var ( +const ( _ float64 = - /* ERROR "overflow" */ (maxFloat64 + delta64) _ float64 = -maxFloat64 _ float64 = maxFloat64 _ float64 = maxFloat64 /* ERROR "overflow" */ + delta64 + + _ = float64(- /* ERROR "cannot convert" */ (maxFloat64 + delta64)) + _ = float64(-maxFloat64) + _ = float64(maxFloat64) + _ = float64(maxFloat64 /* ERROR "cannot convert" */ + delta64) ) -var ( +const ( _ complex64 = - /* ERROR "overflow" */ (maxFloat32 + delta32) _ complex64 = -maxFloat32 _ complex64 = maxFloat32 _ complex64 = maxFloat32 /* ERROR "overflow" */ + delta32 + + _ = complex64(- /* ERROR "cannot convert" */ (maxFloat32 + delta32)) + _ = complex64(-maxFloat32) + _ = complex64(maxFloat32) + _ = complex64(maxFloat32 /* ERROR "cannot convert" */ + delta32) ) -var ( +const ( _ complex128 = - /* ERROR "overflow" */ (maxFloat64 + delta64) _ complex128 = -maxFloat64 _ complex128 = maxFloat64 _ complex128 = maxFloat64 /* ERROR "overflow" */ + delta64 -) \ No newline at end of file + + _ = complex128(- /* ERROR "cannot convert" */ (maxFloat64 + delta64)) + _ = complex128(-maxFloat64) + _ = complex128(maxFloat64) + _ = complex128(maxFloat64 /* ERROR "cannot convert" */ + delta64) +) + +// Initialization of typed constant and conversion are the same: +const ( + f32 = 1 + smallestFloat32 + x32 float32 = f32 + y32 = float32(f32) + _ = assert(x32 - y32 == 0) +) + +const ( + f64 = 1 + smallestFloat64 + x64 float64 = f64 + y64 = float64(f64) + _ = assert(x64 - y64 == 0) +) diff --git a/go/types/testdata/conversions.src b/go/types/testdata/conversions.src index f6fa1bae..7bc4c26c 100644 --- a/go/types/testdata/conversions.src +++ b/go/types/testdata/conversions.src @@ -8,10 +8,12 @@ package conversions // argument count var ( - _ = int /* ERROR "one argument" */ () - _ = int /* ERROR "one argument" */ (1, 2) + _ = int() /* ERROR "missing argument" */ + _ = int(1, 2 /* ERROR "too many arguments" */ ) ) +// numeric constant conversions are in const1.src. + func string_conversions() { const A = string(65) assert(A == "A") @@ -25,16 +27,11 @@ func string_conversions() { 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) + const _ = string(true /* ERROR "cannot convert" */ ) + const _ = string(1.2 /* ERROR "cannot convert" */ ) + const _ = string(nil /* ERROR "cannot convert" */ ) } -// -var ( - _ = int8(0) -) - func interface_conversions() { type E interface{} @@ -63,20 +60,20 @@ func interface_conversions() { _ = E(i1) _ = E(i2) - _ = I1 /* ERROR "cannot convert" */ (0) + _ = I1(0 /* ERROR "cannot convert" */ ) _ = I1(nil) _ = I1(i1) - _ = I1 /* ERROR "cannot convert" */ (e) + _ = I1(e /* ERROR "cannot convert" */ ) _ = I1(i2) _ = I2(nil) - _ = I2 /* ERROR "cannot convert" */ (i1) + _ = I2(i1 /* ERROR "cannot convert" */ ) _ = I2(i2) - _ = I2 /* ERROR "cannot convert" */ (i3) + _ = I2(i3 /* ERROR "cannot convert" */ ) _ = I3(nil) - _ = I3 /* ERROR "cannot convert" */ (i1) - _ = I3 /* ERROR "cannot convert" */ (i2) + _ = I3(i1 /* ERROR "cannot convert" */ ) + _ = I3(i2 /* ERROR "cannot convert" */ ) _ = I3(i3) // TODO(gri) add more tests, improve error message diff --git a/go/types/testdata/expr3.src b/go/types/testdata/expr3.src index 596a6043..96434f9b 100644 --- a/go/types/testdata/expr3.src +++ b/go/types/testdata/expr3.src @@ -317,7 +317,7 @@ func _calls() { f1(0) f1(x) f1(10.0) - f1 /* ERROR "too few arguments" */ () + f1() /* ERROR "too few arguments" */ f1(x, y /* ERROR "too many arguments" */ ) f1(s /* ERROR "cannot pass" */ ) f1(x ... /* ERROR "cannot use ..." */ ) @@ -325,15 +325,15 @@ func _calls() { f1(g1()) // f1(g2()) // TODO(gri) missing position in error message - f2 /* ERROR "too few arguments" */ () - f2 /* ERROR "too few arguments" */ (3.14) + f2() /* ERROR "too few arguments" */ + f2(3.14) /* ERROR "too few arguments" */ f2(3.14, "foo") f2(x /* ERROR "cannot pass" */ , "foo") f2(g0 /* ERROR "used as value" */ ()) - f2 /* ERROR "too few arguments" */ (g1 /* ERROR "cannot pass" */ ()) + f2(g1 /* ERROR "cannot pass" */ ()) /* ERROR "too few arguments" */ f2(g2()) - fs /* ERROR "too few arguments" */ () + fs() /* ERROR "too few arguments" */ fs(g0 /* ERROR "used as value" */ ()) fs(g1 /* ERROR "cannot pass" */ ()) fs(g2 /* ERROR "cannot pass" */ /* ERROR "too many arguments" */ ()) diff --git a/go/types/testdata/stmt0.src b/go/types/testdata/stmt0.src index d148caaf..24b54b97 100644 --- a/go/types/testdata/stmt0.src +++ b/go/types/testdata/stmt0.src @@ -54,7 +54,7 @@ func assignments() { g := func(int, bool){} var m map[int]int - g/* ERROR "too few arguments" */ (m[0]) + g(m[0]) /* ERROR "too few arguments" */ // assignments to _ _ = nil /* ERROR "use of untyped nil" */