Skip to content

Commit

Permalink
reflect: add Overflow methods to Type
Browse files Browse the repository at this point in the history
This CL adds new methods synonymous with the method of the same name
in reflect.Value to reflect.Type: OverflowComplex, OverflowFloat, OverflowInt, OverflowUint.

Fixes #60427

Change-Id: I7a0bb35629e59a7429820f13fcd3a6f120194bc6
GitHub-Last-Rev: 26c11bc
GitHub-Pull-Request: #65955
Reviewed-on: https://go-review.googlesource.com/c/go/+/567296
Auto-Submit: Ian Lance Taylor <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
callthingsoff authored and gopherbot committed Feb 28, 2024
1 parent 1571c0b commit 33013e8
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 1 deletion.
4 changes: 4 additions & 0 deletions api/next/60427.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pkg reflect, type Type interface, OverflowComplex(complex128) bool #60427
pkg reflect, type Type interface, OverflowFloat(float64) bool #60427
pkg reflect, type Type interface, OverflowInt(int64) bool #60427
pkg reflect, type Type interface, OverflowUint(uint64) bool #60427
6 changes: 6 additions & 0 deletions doc/next/6-stdlib/99-minor/reflect/60427.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The new methods synonymous with the method of the same name in [`reflect.Value`](/pkg/reflect#Value)
are added to [`reflect.Type`](/pkg/reflect#Type):
1. [`OverflowComplex`](/pkg/reflect#Type.OverflowComplex)
2. [`OverflowFloat`](/pkg/reflect#Type.OverflowFloat)
3. [`OverflowInt`](/pkg/reflect#Type.OverflowInt)
4. [`OverflowUint`](/pkg/reflect#Type.OverflowUint)
41 changes: 40 additions & 1 deletion src/reflect/all_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4827,7 +4827,7 @@ func TestComparable(t *testing.T) {
}
}

func TestOverflow(t *testing.T) {
func TestValueOverflow(t *testing.T) {
if ovf := V(float64(0)).OverflowFloat(1e300); ovf {
t.Errorf("%v wrongly overflows float64", 1e300)
}
Expand Down Expand Up @@ -4866,6 +4866,45 @@ func TestOverflow(t *testing.T) {
}
}

func TestTypeOverflow(t *testing.T) {
if ovf := TypeFor[float64]().OverflowFloat(1e300); ovf {
t.Errorf("%v wrongly overflows float64", 1e300)
}

maxFloat32 := float64((1<<24 - 1) << (127 - 23))
if ovf := TypeFor[float32]().OverflowFloat(maxFloat32); ovf {
t.Errorf("%v wrongly overflows float32", maxFloat32)
}
ovfFloat32 := float64((1<<24-1)<<(127-23) + 1<<(127-52))
if ovf := TypeFor[float32]().OverflowFloat(ovfFloat32); !ovf {
t.Errorf("%v should overflow float32", ovfFloat32)
}
if ovf := TypeFor[float32]().OverflowFloat(-ovfFloat32); !ovf {
t.Errorf("%v should overflow float32", -ovfFloat32)
}

maxInt32 := int64(0x7fffffff)
if ovf := TypeFor[int32]().OverflowInt(maxInt32); ovf {
t.Errorf("%v wrongly overflows int32", maxInt32)
}
if ovf := TypeFor[int32]().OverflowInt(-1 << 31); ovf {
t.Errorf("%v wrongly overflows int32", -int64(1)<<31)
}
ovfInt32 := int64(1 << 31)
if ovf := TypeFor[int32]().OverflowInt(ovfInt32); !ovf {
t.Errorf("%v should overflow int32", ovfInt32)
}

maxUint32 := uint64(0xffffffff)
if ovf := TypeFor[uint32]().OverflowUint(maxUint32); ovf {
t.Errorf("%v wrongly overflows uint32", maxUint32)
}
ovfUint32 := uint64(1 << 32)
if ovf := TypeFor[uint32]().OverflowUint(ovfUint32); !ovf {
t.Errorf("%v should overflow uint32", ovfUint32)
}
}

func checkSameType(t *testing.T, x Type, y any) {
if x != TypeOf(y) || TypeOf(Zero(x).Interface()) != TypeOf(y) {
t.Errorf("did not find preexisting type for %s (vs %s)", TypeOf(x), TypeOf(y))
Expand Down
68 changes: 68 additions & 0 deletions src/reflect/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,22 @@ type Type interface {
// It panics if i is not in the range [0, NumOut()).
Out(i int) Type

// OverflowComplex reports whether the complex128 x cannot be represented by type t.
// It panics if t's Kind is not Complex64 or Complex128.
OverflowComplex(x complex128) bool

// OverflowFloat reports whether the float64 x cannot be represented by type t.
// It panics if t's Kind is not Float32 or Float64.
OverflowFloat(x float64) bool

// OverflowInt reports whether the int64 x cannot be represented by type t.
// It panics if t's Kind is not Int, Int8, Int16, Int32, or Int64.
OverflowInt(x int64) bool

// OverflowUint reports whether the uint64 x cannot be represented by type t.
// It panics if t's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
OverflowUint(x uint64) bool

common() *abi.Type
uncommon() *uncommonType
}
Expand Down Expand Up @@ -297,6 +313,58 @@ type rtype struct {
t abi.Type
}

// OverflowComplex reports whether the complex128 x cannot be represented by type t.
// It panics if t's Kind is not Complex64 or Complex128.
func (t *rtype) OverflowComplex(x complex128) bool {
k := t.Kind()
switch k {
case Complex64:
return overflowFloat32(real(x)) || overflowFloat32(imag(x))
case Complex128:
return false
}
panic("reflect: OverflowComplex of non-complex type " + t.String())
}

// OverflowFloat reports whether the float64 x cannot be represented by type t.
// It panics if t's Kind is not Float32 or Float64.
func (t *rtype) OverflowFloat(x float64) bool {
k := t.Kind()
switch k {
case Float32:
return overflowFloat32(x)
case Float64:
return false
}
panic("reflect: OverflowFloat of non-float type " + t.String())
}

// OverflowInt reports whether the int64 x cannot be represented by type t.
// It panics if t's Kind is not Int, Int8, Int16, Int32, or Int64.
func (t *rtype) OverflowInt(x int64) bool {
k := t.Kind()
switch k {
case Int, Int8, Int16, Int32, Int64:
bitSize := t.Size() * 8
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
}
panic("reflect: OverflowInt of non-int type " + t.String())
}

// OverflowUint reports whether the uint64 x cannot be represented by type t.
// It panics if t's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
func (t *rtype) OverflowUint(x uint64) bool {
k := t.Kind()
switch k {
case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
bitSize := t.Size() * 8
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
}
panic("reflect: OverflowUint of non-uint type " + t.String())
}

func (t *rtype) common() *abi.Type {
return &t.t
}
Expand Down

0 comments on commit 33013e8

Please sign in to comment.