go.tools/go/types: report correctly rounded constant values
Also: - better documentation of exact.Float64Val - minor rearrangement in go/importer (unrelated) LGTM=adonovan R=adonovan CC=golang-codereviews https://golang.org/cl/70200047
This commit is contained in:
parent
fccaf8c467
commit
e3ab342481
|
|
@ -244,7 +244,9 @@ func Uint64Val(x Value) (uint64, bool) {
|
|||
}
|
||||
|
||||
// Float64Val returns the nearest Go float64 value of x and whether the result is exact;
|
||||
// x must be numeric but not Complex, or Unknown.
|
||||
// x must be numeric but not Complex, or Unknown. For values too small (too close to 0)
|
||||
// to represent as float64, Float64Val silently underflows to 0. The result sign always
|
||||
// matches the sign of x, even for 0.
|
||||
// If x is Unknown, the result is (0, false).
|
||||
func Float64Val(x Value) (float64, bool) {
|
||||
switch x := x.(type) {
|
||||
|
|
|
|||
|
|
@ -137,9 +137,6 @@ func (p *exporter) value(x exact.Value) {
|
|||
tag = trueTag
|
||||
}
|
||||
p.int(tag)
|
||||
case exact.String:
|
||||
p.int(stringTag)
|
||||
p.string(exact.StringVal(x))
|
||||
case exact.Int:
|
||||
if i, ok := exact.Int64Val(x); ok {
|
||||
p.int(int64Tag)
|
||||
|
|
@ -155,6 +152,9 @@ func (p *exporter) value(x exact.Value) {
|
|||
p.int(complexTag)
|
||||
p.fraction(exact.Real(x))
|
||||
p.fraction(exact.Imag(x))
|
||||
case exact.String:
|
||||
p.int(stringTag)
|
||||
p.string(exact.StringVal(x))
|
||||
default:
|
||||
panic(fmt.Sprintf("unexpected value kind %d", kind))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,8 +129,6 @@ func (p *importer) value() exact.Value {
|
|||
return exact.MakeBool(false)
|
||||
case trueTag:
|
||||
return exact.MakeBool(true)
|
||||
case stringTag:
|
||||
return exact.MakeString(p.string())
|
||||
case int64Tag:
|
||||
return exact.MakeInt64(p.int64())
|
||||
case floatTag:
|
||||
|
|
@ -141,6 +139,8 @@ func (p *importer) value() exact.Value {
|
|||
re := p.fraction()
|
||||
im := p.fraction()
|
||||
return exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
|
||||
case stringTag:
|
||||
return exact.MakeString(p.string())
|
||||
default:
|
||||
panic(fmt.Sprintf("unexpected value kind %d", kind))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// TODO(gri) This file needs to be expanded significantly.
|
||||
|
||||
package types_test
|
||||
|
||||
import (
|
||||
|
|
@ -89,6 +87,28 @@ func TestValuesInfo(t *testing.T) {
|
|||
{`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
|
||||
{`package d2; var _ = []byte(string("foo"))`, `string("foo")`, `string`, `"foo"`},
|
||||
{`package d3; type T []byte; var _ = T("foo")`, `"foo"`, `string`, `"foo"`},
|
||||
|
||||
{`package e0; const _ = float32( 1e-200)`, `float32(1e-200)`, `float32`, `0`},
|
||||
{`package e1; const _ = float32(-1e-200)`, `float32(-1e-200)`, `float32`, `0`},
|
||||
{`package e2; const _ = float64( 1e-2000)`, `float64(1e-2000)`, `float64`, `0`},
|
||||
{`package e3; const _ = float64(-1e-2000)`, `float64(-1e-2000)`, `float64`, `0`},
|
||||
{`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `0`},
|
||||
{`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `0`},
|
||||
{`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `0`},
|
||||
{`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `0`},
|
||||
|
||||
{`package f0 ; var _ float32 = 1e-200`, `1e-200`, `float32`, `0`},
|
||||
{`package f1 ; var _ float32 = -1e-200`, `-1e-200`, `float32`, `0`},
|
||||
{`package f2a; var _ float64 = 1e-2000`, `1e-2000`, `float64`, `0`},
|
||||
{`package f3a; var _ float64 = -1e-2000`, `-1e-2000`, `float64`, `0`},
|
||||
{`package f2b; var _ = 1e-2000`, `1e-2000`, `float64`, `0`},
|
||||
{`package f3b; var _ = -1e-2000`, `-1e-2000`, `float64`, `0`},
|
||||
{`package f4 ; var _ complex64 = 1e-200 `, `1e-200`, `complex64`, `0`},
|
||||
{`package f5 ; var _ complex64 = -1e-200 `, `-1e-200`, `complex64`, `0`},
|
||||
{`package f6a; var _ complex128 = 1e-2000i`, `1e-2000i`, `complex128`, `0`},
|
||||
{`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
|
||||
{`package f6b; var _ = 1e-2000i`, `1e-2000i`, `complex128`, `0`},
|
||||
{`package f7b; var _ = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
|
|||
|
|
@ -57,10 +57,10 @@ func (check *checker) conversion(x *operand, T Type) {
|
|||
if isInterface(T) || constArg && !isConstType(T) {
|
||||
final = defaultType(x.typ)
|
||||
}
|
||||
check.updateExprType(x.expr, final, true)
|
||||
}
|
||||
|
||||
x.typ = T
|
||||
check.updateExprType(x.expr, final, true)
|
||||
}
|
||||
|
||||
func (x *operand) convertibleTo(conf *Config, T Type) bool {
|
||||
|
|
|
|||
|
|
@ -462,6 +462,14 @@ func (check *checker) updateExprType(x ast.Expr, typ Type, final bool) {
|
|||
check.recordTypeAndValue(x, typ, old.val)
|
||||
}
|
||||
|
||||
// updateExprVal updates the value of x to val.
|
||||
func (check *checker) updateExprVal(x ast.Expr, val exact.Value) {
|
||||
if info, ok := check.untyped[x]; ok {
|
||||
info.val = val
|
||||
check.untyped[x] = info
|
||||
}
|
||||
}
|
||||
|
||||
// convertUntyped attempts to set the type of an untyped value to the target type.
|
||||
func (check *checker) convertUntyped(x *operand, target Type) {
|
||||
if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] {
|
||||
|
|
@ -494,6 +502,10 @@ func (check *checker) convertUntyped(x *operand, target Type) {
|
|||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
// expression value may have been rounded - update if needed
|
||||
// TODO(gri) A floating-point value may silently underflow to
|
||||
// zero. If it was negative, the sign is lost. See issue 6898.
|
||||
check.updateExprVal(x.expr, x.val)
|
||||
} else {
|
||||
// Non-constant untyped values may appear as the
|
||||
// result of comparisons (untyped bool), intermediate
|
||||
|
|
|
|||
Loading…
Reference in New Issue