Skip to content

Commit e300e90

Browse files
aykevldeadprogram
authored andcommitted
reflect: implement Type.Overflow* functions
They're already implemented for the Value equivalents. But since Go 1.23, such methods also exist for reflect.Type.
1 parent e865db2 commit e300e90

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed

src/reflect/all_test.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4897,7 +4897,7 @@ func TestComparable(t *testing.T) {
48974897
}
48984898
}
48994899

4900-
func TestOverflow(t *testing.T) {
4900+
func TestValueOverflow(t *testing.T) {
49014901
if ovf := V(float64(0)).OverflowFloat(1e300); ovf {
49024902
t.Errorf("%v wrongly overflows float64", 1e300)
49034903
}
@@ -4936,6 +4936,45 @@ func TestOverflow(t *testing.T) {
49364936
}
49374937
}
49384938

4939+
func TestTypeOverflow(t *testing.T) {
4940+
if ovf := TypeFor[float64]().OverflowFloat(1e300); ovf {
4941+
t.Errorf("%v wrongly overflows float64", 1e300)
4942+
}
4943+
4944+
maxFloat32 := float64((1<<24 - 1) << (127 - 23))
4945+
if ovf := TypeFor[float32]().OverflowFloat(maxFloat32); ovf {
4946+
t.Errorf("%v wrongly overflows float32", maxFloat32)
4947+
}
4948+
ovfFloat32 := float64((1<<24-1)<<(127-23) + 1<<(127-52))
4949+
if ovf := TypeFor[float32]().OverflowFloat(ovfFloat32); !ovf {
4950+
t.Errorf("%v should overflow float32", ovfFloat32)
4951+
}
4952+
if ovf := TypeFor[float32]().OverflowFloat(-ovfFloat32); !ovf {
4953+
t.Errorf("%v should overflow float32", -ovfFloat32)
4954+
}
4955+
4956+
maxInt32 := int64(0x7fffffff)
4957+
if ovf := TypeFor[int32]().OverflowInt(maxInt32); ovf {
4958+
t.Errorf("%v wrongly overflows int32", maxInt32)
4959+
}
4960+
if ovf := TypeFor[int32]().OverflowInt(-1 << 31); ovf {
4961+
t.Errorf("%v wrongly overflows int32", -int64(1)<<31)
4962+
}
4963+
ovfInt32 := int64(1 << 31)
4964+
if ovf := TypeFor[int32]().OverflowInt(ovfInt32); !ovf {
4965+
t.Errorf("%v should overflow int32", ovfInt32)
4966+
}
4967+
4968+
maxUint32 := uint64(0xffffffff)
4969+
if ovf := TypeFor[uint32]().OverflowUint(maxUint32); ovf {
4970+
t.Errorf("%v wrongly overflows uint32", maxUint32)
4971+
}
4972+
ovfUint32 := uint64(1 << 32)
4973+
if ovf := TypeFor[uint32]().OverflowUint(ovfUint32); !ovf {
4974+
t.Errorf("%v should overflow uint32", ovfUint32)
4975+
}
4976+
}
4977+
49394978
/*
49404979
49414980
func checkSameType(t *testing.T, x Type, y any) {

src/reflect/type.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,22 @@ type Type interface {
392392
// It panics if the type's Kind is not Func.
393393
// It panics if i is not in the range [0, NumOut()).
394394
Out(i int) Type
395+
396+
// OverflowComplex reports whether the complex128 x cannot be represented by type t.
397+
// It panics if t's Kind is not Complex64 or Complex128.
398+
OverflowComplex(x complex128) bool
399+
400+
// OverflowFloat reports whether the float64 x cannot be represented by type t.
401+
// It panics if t's Kind is not Float32 or Float64.
402+
OverflowFloat(x float64) bool
403+
404+
// OverflowInt reports whether the int64 x cannot be represented by type t.
405+
// It panics if t's Kind is not Int, Int8, Int16, Int32, or Int64.
406+
OverflowInt(x int64) bool
407+
408+
// OverflowUint reports whether the uint64 x cannot be represented by type t.
409+
// It panics if t's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
410+
OverflowUint(x uint64) bool
395411
}
396412

397413
// Constants for the 'meta' byte.
@@ -1081,6 +1097,58 @@ func (t rawType) Out(i int) Type {
10811097
panic("unimplemented: (reflect.Type).Out()")
10821098
}
10831099

1100+
// OverflowComplex reports whether the complex128 x cannot be represented by type t.
1101+
// It panics if t's Kind is not Complex64 or Complex128.
1102+
func (t rawType) OverflowComplex(x complex128) bool {
1103+
k := t.Kind()
1104+
switch k {
1105+
case Complex64:
1106+
return overflowFloat32(real(x)) || overflowFloat32(imag(x))
1107+
case Complex128:
1108+
return false
1109+
}
1110+
panic("reflect: OverflowComplex of non-complex type")
1111+
}
1112+
1113+
// OverflowFloat reports whether the float64 x cannot be represented by type t.
1114+
// It panics if t's Kind is not Float32 or Float64.
1115+
func (t rawType) OverflowFloat(x float64) bool {
1116+
k := t.Kind()
1117+
switch k {
1118+
case Float32:
1119+
return overflowFloat32(x)
1120+
case Float64:
1121+
return false
1122+
}
1123+
panic("reflect: OverflowFloat of non-float type")
1124+
}
1125+
1126+
// OverflowInt reports whether the int64 x cannot be represented by type t.
1127+
// It panics if t's Kind is not Int, Int8, Int16, Int32, or Int64.
1128+
func (t rawType) OverflowInt(x int64) bool {
1129+
k := t.Kind()
1130+
switch k {
1131+
case Int, Int8, Int16, Int32, Int64:
1132+
bitSize := t.Size() * 8
1133+
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
1134+
return x != trunc
1135+
}
1136+
panic("reflect: OverflowInt of non-int type")
1137+
}
1138+
1139+
// OverflowUint reports whether the uint64 x cannot be represented by type t.
1140+
// It panics if t's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
1141+
func (t rawType) OverflowUint(x uint64) bool {
1142+
k := t.Kind()
1143+
switch k {
1144+
case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
1145+
bitSize := t.Size() * 8
1146+
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
1147+
return x != trunc
1148+
}
1149+
panic("reflect: OverflowUint of non-uint type")
1150+
}
1151+
10841152
func (t rawType) Method(i int) Method {
10851153
panic("unimplemented: (reflect.Type).Method()")
10861154
}

0 commit comments

Comments
 (0)