From a93640662e9d9bfa0fab90c2c01441d53be6a93f Mon Sep 17 00:00:00 2001 From: Damian Gryski Date: Mon, 25 May 2026 11:07:52 -0700 Subject: [PATCH] reflect: add Type.ConvertibleTo --- src/internal/reflectlite/type.go | 87 ++++++++++++++++++++++++++++++++ src/reflect/type.go | 2 +- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go index 4fd02e67b..6462b3a0c 100644 --- a/src/internal/reflectlite/type.go +++ b/src/internal/reflectlite/type.go @@ -754,6 +754,93 @@ func (t *RawType) FieldAlign() int { return t.Align() } +// ConvertibleTo returns wheather a value of type t can be converted to a variable of of type u + +func (r *RawType) ConvertibleTo(u *RawType) bool { + + // This logic is mostly copied from Value.CanConvert + + // Don't need to do anything + if r.underlying() == u.underlying() { + return true + } + + switch r.Kind() { + case Int, Int8, Int16, Int32, Int64: + switch u.Kind() { + case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + return true + case Float32, Float64: + return true + case String: + return true + } + + case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + switch u.Kind() { + case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + return true + case Float32, Float64: + return true + case String: + return true + } + + case Float32, Float64: + switch u.Kind() { + case Int, Int8, Int16, Int32, Int64: + return true + case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + return true + case Float32, Float64: + return true + } + + case Complex64, Complex128: + switch u.Kind() { + case Complex64, Complex128: + return true + } + + case Slice: + switch u.Kind() { + case Array: + // This may fail at runtime if there isn't room + if r.elem() == u.elem() { + return true + } + + case Pointer: + // This may fail at runtime if there isn't room + if u.elem().Kind() == Array { + return true + } + + case String: + // bytes or runes + if r.elem().Kind() == Uint8 || r.elem().Kind() == Int32 { + return true + } + + } + + case String: + // bytes or runes + if u.elem().Kind() == Uint8 || u.elem().Kind() == Int32 { + return true + } + + } + + // TODO(dgryski): Unimplemented + // struct types + // channels + // + + return false + +} + // AssignableTo returns whether a value of type t can be assigned to a variable // of type u. func (t *RawType) AssignableTo(u Type) bool { diff --git a/src/reflect/type.go b/src/reflect/type.go index 884f89dc8..9357cef52 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -402,7 +402,7 @@ func (t *rawType) CanSeq2() bool { } func (t *rawType) ConvertibleTo(u Type) bool { - panic("unimplemented: (reflect.Type).ConvertibleTo()") + return t.RawType.Convertibleto(u.(*rawType).RawType) } func (t *rawType) Elem() Type {