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
This commit is contained in:
parent
508ae115ae
commit
d13d94afe7
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
_ = 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)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" */ ())
|
||||
|
|
|
@ -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" */
|
||||
|
|
Loading…
Reference in New Issue