@@ -3,7 +3,9 @@ package reflect_test
33import (
44 "bytes"
55 "encoding/base64"
6+ "fmt"
67 . "reflect"
8+ "runtime"
79 "slices"
810 "sort"
911 "strings"
@@ -869,3 +871,77 @@ func equal[T comparable](a, b []T) bool {
869871 }
870872 return true
871873}
874+
875+ func TestTypeAssert (t * testing.T ) {
876+ testTypeAssert (t , int (123456789 ), int (123456789 ), true )
877+ testTypeAssert (t , int (- 123456789 ), int (- 123456789 ), true )
878+ testTypeAssert (t , int32 (123456789 ), int32 (123456789 ), true )
879+ testTypeAssert (t , int8 (- 123 ), int8 (- 123 ), true )
880+ testTypeAssert (t , [2 ]int {1234 , - 5678 }, [2 ]int {1234 , - 5678 }, true )
881+ testTypeAssert (t , "test value" , "test value" , true )
882+ testTypeAssert (t , any ("test value" ), any ("test value" ), true )
883+
884+ v := 123456789
885+ testTypeAssert (t , & v , & v , true )
886+
887+ testTypeAssert (t , int (123 ), uint (0 ), false )
888+
889+ testTypeAssert [any ](t , 1 , 1 , true )
890+ testTypeAssert [fmt.Stringer ](t , 1 , nil , false )
891+
892+ vv := testTypeWithMethod {"test" }
893+ testTypeAssert [any ](t , vv , vv , true )
894+ testTypeAssert [any ](t , & vv , & vv , true )
895+ testTypeAssert [fmt.Stringer ](t , vv , vv , true )
896+ testTypeAssert [fmt.Stringer ](t , & vv , & vv , true )
897+ testTypeAssert [interface { A () }](t , vv , nil , false )
898+ testTypeAssert [interface { A () }](t , & vv , nil , false )
899+ testTypeAssert (t , any (vv ), any (vv ), true )
900+ testTypeAssert (t , fmt .Stringer (vv ), fmt .Stringer (vv ), true )
901+
902+ testTypeAssert (t , fmt .Stringer (vv ), any (vv ), true )
903+ testTypeAssert (t , any (vv ), fmt .Stringer (vv ), true )
904+ testTypeAssert (t , fmt .Stringer (vv ), interface { M () }(vv ), true )
905+ testTypeAssert (t , interface { M () }(vv ), fmt .Stringer (vv ), true )
906+
907+ testTypeAssert (t , any (int (1 )), int (1 ), true )
908+ testTypeAssert (t , any (int (1 )), byte (0 ), false )
909+ testTypeAssert (t , fmt .Stringer (vv ), vv , true )
910+ }
911+
912+ func testTypeAssert [T comparable , V any ](t * testing.T , val V , wantVal T , wantOk bool ) {
913+ t .Helper ()
914+
915+ v , ok := TypeAssert [T ](ValueOf (& val ).Elem ())
916+ if v != wantVal || ok != wantOk {
917+ t .Errorf ("TypeAssert[%v](%#v) = (%#v, %v); want = (%#v, %v)" , TypeFor [T ](), val , v , ok , wantVal , wantOk )
918+ }
919+
920+ // Additionally make sure that TypeAssert[T](v) behaves in the same way as v.Interface().(T).
921+ v2 , ok2 := ValueOf (& val ).Elem ().Interface ().(T )
922+ if v != v2 || ok != ok2 {
923+ t .Errorf ("reflect.ValueOf(%#v).Interface().(%v) = (%#v, %v); want = (%#v, %v)" , val , TypeFor [T ](), v2 , ok2 , v , ok )
924+ }
925+ }
926+
927+ type testTypeWithMethod struct { val string }
928+
929+ func (v testTypeWithMethod ) String () string { return v .val }
930+ func (v testTypeWithMethod ) M () {}
931+
932+ func TestTypeAssertPanic (t * testing.T ) {
933+ if runtime .GOARCH == "wasm" {
934+ t .Skip ("recover not supported" )
935+ }
936+
937+ t .Run ("zero val" , func (t * testing.T ) {
938+ defer func () { recover () }()
939+ TypeAssert [int ](Value {})
940+ t .Fatalf ("TypeAssert did not panic" )
941+ })
942+ t .Run ("read only" , func (t * testing.T ) {
943+ defer func () { recover () }()
944+ TypeAssert [int ](ValueOf (& testTypeWithMethod {}).FieldByName ("val" ))
945+ t .Fatalf ("TypeAssert did not panic" )
946+ })
947+ }
0 commit comments