aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/reflect
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2024-06-24 16:24:22 +0200
committerRon Evans <[email protected]>2024-08-17 11:49:14 +0200
commite300e90a637a6107fb18389fb4091c12fd3054b2 (patch)
treeb7134bb4198a8ceea14fcdfbb31868f7d61223be /src/reflect
parente865db232bad0a2a5152749edd6a9ce32557c8b7 (diff)
downloadtinygo-e300e90a637a6107fb18389fb4091c12fd3054b2.tar.gz
tinygo-e300e90a637a6107fb18389fb4091c12fd3054b2.zip
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.
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/all_test.go41
-rw-r--r--src/reflect/type.go68
2 files changed, 108 insertions, 1 deletions
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 4c2fcc48b..436bc0034 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -4897,7 +4897,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)
}
@@ -4936,6 +4936,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) {
diff --git a/src/reflect/type.go b/src/reflect/type.go
index aa84c77a2..5dd59b329 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -392,6 +392,22 @@ type Type interface {
// It panics if the type's Kind is not Func.
// 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
}
// Constants for the 'meta' byte.
@@ -1081,6 +1097,58 @@ func (t rawType) Out(i int) Type {
panic("unimplemented: (reflect.Type).Out()")
}
+// 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 rawType) 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")
+}
+
+// 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 rawType) 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")
+}
+
+// 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 rawType) 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")
+}
+
+// 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 rawType) 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")
+}
+
func (t rawType) Method(i int) Method {
panic("unimplemented: (reflect.Type).Method()")
}