Skip to content

Commit 33013e8

Browse files
callthingsoffgopherbot
authored andcommitted
reflect: add Overflow methods to Type
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]>
1 parent 1571c0b commit 33013e8

File tree

4 files changed

+118
-1
lines changed

4 files changed

+118
-1
lines changed

api/next/60427.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pkg reflect, type Type interface, OverflowComplex(complex128) bool #60427
2+
pkg reflect, type Type interface, OverflowFloat(float64) bool #60427
3+
pkg reflect, type Type interface, OverflowInt(int64) bool #60427
4+
pkg reflect, type Type interface, OverflowUint(uint64) bool #60427
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
The new methods synonymous with the method of the same name in [`reflect.Value`](/pkg/reflect#Value)
2+
are added to [`reflect.Type`](/pkg/reflect#Type):
3+
1. [`OverflowComplex`](/pkg/reflect#Type.OverflowComplex)
4+
2. [`OverflowFloat`](/pkg/reflect#Type.OverflowFloat)
5+
3. [`OverflowInt`](/pkg/reflect#Type.OverflowInt)
6+
4. [`OverflowUint`](/pkg/reflect#Type.OverflowUint)

src/reflect/all_test.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4827,7 +4827,7 @@ func TestComparable(t *testing.T) {
48274827
}
48284828
}
48294829

4830-
func TestOverflow(t *testing.T) {
4830+
func TestValueOverflow(t *testing.T) {
48314831
if ovf := V(float64(0)).OverflowFloat(1e300); ovf {
48324832
t.Errorf("%v wrongly overflows float64", 1e300)
48334833
}
@@ -4866,6 +4866,45 @@ func TestOverflow(t *testing.T) {
48664866
}
48674867
}
48684868

4869+
func TestTypeOverflow(t *testing.T) {
4870+
if ovf := TypeFor[float64]().OverflowFloat(1e300); ovf {
4871+
t.Errorf("%v wrongly overflows float64", 1e300)
4872+
}
4873+
4874+
maxFloat32 := float64((1<<24 - 1) << (127 - 23))
4875+
if ovf := TypeFor[float32]().OverflowFloat(maxFloat32); ovf {
4876+
t.Errorf("%v wrongly overflows float32", maxFloat32)
4877+
}
4878+
ovfFloat32 := float64((1<<24-1)<<(127-23) + 1<<(127-52))
4879+
if ovf := TypeFor[float32]().OverflowFloat(ovfFloat32); !ovf {
4880+
t.Errorf("%v should overflow float32", ovfFloat32)
4881+
}
4882+
if ovf := TypeFor[float32]().OverflowFloat(-ovfFloat32); !ovf {
4883+
t.Errorf("%v should overflow float32", -ovfFloat32)
4884+
}
4885+
4886+
maxInt32 := int64(0x7fffffff)
4887+
if ovf := TypeFor[int32]().OverflowInt(maxInt32); ovf {
4888+
t.Errorf("%v wrongly overflows int32", maxInt32)
4889+
}
4890+
if ovf := TypeFor[int32]().OverflowInt(-1 << 31); ovf {
4891+
t.Errorf("%v wrongly overflows int32", -int64(1)<<31)
4892+
}
4893+
ovfInt32 := int64(1 << 31)
4894+
if ovf := TypeFor[int32]().OverflowInt(ovfInt32); !ovf {
4895+
t.Errorf("%v should overflow int32", ovfInt32)
4896+
}
4897+
4898+
maxUint32 := uint64(0xffffffff)
4899+
if ovf := TypeFor[uint32]().OverflowUint(maxUint32); ovf {
4900+
t.Errorf("%v wrongly overflows uint32", maxUint32)
4901+
}
4902+
ovfUint32 := uint64(1 << 32)
4903+
if ovf := TypeFor[uint32]().OverflowUint(ovfUint32); !ovf {
4904+
t.Errorf("%v should overflow uint32", ovfUint32)
4905+
}
4906+
}
4907+
48694908
func checkSameType(t *testing.T, x Type, y any) {
48704909
if x != TypeOf(y) || TypeOf(Zero(x).Interface()) != TypeOf(y) {
48714910
t.Errorf("did not find preexisting type for %s (vs %s)", TypeOf(x), TypeOf(y))

src/reflect/type.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,22 @@ type Type interface {
225225
// It panics if i is not in the range [0, NumOut()).
226226
Out(i int) Type
227227

228+
// OverflowComplex reports whether the complex128 x cannot be represented by type t.
229+
// It panics if t's Kind is not Complex64 or Complex128.
230+
OverflowComplex(x complex128) bool
231+
232+
// OverflowFloat reports whether the float64 x cannot be represented by type t.
233+
// It panics if t's Kind is not Float32 or Float64.
234+
OverflowFloat(x float64) bool
235+
236+
// OverflowInt reports whether the int64 x cannot be represented by type t.
237+
// It panics if t's Kind is not Int, Int8, Int16, Int32, or Int64.
238+
OverflowInt(x int64) bool
239+
240+
// OverflowUint reports whether the uint64 x cannot be represented by type t.
241+
// It panics if t's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
242+
OverflowUint(x uint64) bool
243+
228244
common() *abi.Type
229245
uncommon() *uncommonType
230246
}
@@ -297,6 +313,58 @@ type rtype struct {
297313
t abi.Type
298314
}
299315

316+
// OverflowComplex reports whether the complex128 x cannot be represented by type t.
317+
// It panics if t's Kind is not Complex64 or Complex128.
318+
func (t *rtype) OverflowComplex(x complex128) bool {
319+
k := t.Kind()
320+
switch k {
321+
case Complex64:
322+
return overflowFloat32(real(x)) || overflowFloat32(imag(x))
323+
case Complex128:
324+
return false
325+
}
326+
panic("reflect: OverflowComplex of non-complex type " + t.String())
327+
}
328+
329+
// OverflowFloat reports whether the float64 x cannot be represented by type t.
330+
// It panics if t's Kind is not Float32 or Float64.
331+
func (t *rtype) OverflowFloat(x float64) bool {
332+
k := t.Kind()
333+
switch k {
334+
case Float32:
335+
return overflowFloat32(x)
336+
case Float64:
337+
return false
338+
}
339+
panic("reflect: OverflowFloat of non-float type " + t.String())
340+
}
341+
342+
// OverflowInt reports whether the int64 x cannot be represented by type t.
343+
// It panics if t's Kind is not Int, Int8, Int16, Int32, or Int64.
344+
func (t *rtype) OverflowInt(x int64) bool {
345+
k := t.Kind()
346+
switch k {
347+
case Int, Int8, Int16, Int32, Int64:
348+
bitSize := t.Size() * 8
349+
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
350+
return x != trunc
351+
}
352+
panic("reflect: OverflowInt of non-int type " + t.String())
353+
}
354+
355+
// OverflowUint reports whether the uint64 x cannot be represented by type t.
356+
// It panics if t's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
357+
func (t *rtype) OverflowUint(x uint64) bool {
358+
k := t.Kind()
359+
switch k {
360+
case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
361+
bitSize := t.Size() * 8
362+
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
363+
return x != trunc
364+
}
365+
panic("reflect: OverflowUint of non-uint type " + t.String())
366+
}
367+
300368
func (t *rtype) common() *abi.Type {
301369
return &t.t
302370
}

0 commit comments

Comments
 (0)