From 7b20733f5222cee353e75e01353c25847cf53a16 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Sat, 19 Sep 2026 19:22:22 -0700 Subject: [PATCH] reflect: implement NewAt Co-authored-by: Dave Cheney --- src/internal/reflectlite/value.go | 6 +++- src/reflect/value.go | 2 +- src/reflect/value_test.go | 47 +++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go index 9a93e910a5..5555722368 100644 --- a/src/internal/reflectlite/value.go +++ b/src/internal/reflectlite/value.go @@ -2303,5 +2303,9 @@ func (v Value) Recv() (x Value, ok bool) { } func NewAt(typ Type, p unsafe.Pointer) Value { - panic("unimplemented: reflect.New()") + return Value{ + typecode: pointerTo(typ.(*RawType)), + value: p, + flags: valueFlagExported, + } } diff --git a/src/reflect/value.go b/src/reflect/value.go index 66926698b0..f42bd7d8f9 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -235,7 +235,7 @@ func (v Value) TryRecv() (x Value, ok bool) { } func NewAt(typ Type, p unsafe.Pointer) Value { - panic("unimplemented: reflect.New()") + return Value{reflectlite.NewAt(toRawType(typ), p)} } // Deprecated: Use unsafe.Slice or unsafe.SliceData instead. diff --git a/src/reflect/value_test.go b/src/reflect/value_test.go index 0d0b50f230..e108ecf7f3 100644 --- a/src/reflect/value_test.go +++ b/src/reflect/value_test.go @@ -11,6 +11,7 @@ import ( "sort" "strings" "testing" + "unsafe" ) func TestTinyIndirectPointers(t *testing.T) { @@ -45,6 +46,52 @@ func TestTinyInvalidValueString(t *testing.T) { } } +func TestNewAt(t *testing.T) { + value := 42 + v := NewAt(TypeOf(value), unsafe.Pointer(&value)) + if got, want := v.Type(), TypeOf((*int)(nil)); got != want { + t.Fatalf("NewAt type = %v, want %v", got, want) + } + if got := v.Interface().(*int); got != &value { + t.Fatalf("NewAt pointer = %p, want %p", got, &value) + } + v.Elem().SetInt(23) + if value != 23 { + t.Fatalf("NewAt value = %d, want 23", value) + } + if !v.Elem().CanAddr() || !v.Elem().CanSet() { + t.Fatal("NewAt element is not addressable and settable") + } + if got := v.Elem().Addr().Interface(); got != v.Interface() { + t.Fatalf("address of NewAt element = %v, want %v", got, v.Interface()) + } + + type composite struct { + Value int + Pointer *int + } + pointed := 1 + compositeValue := composite{Value: 42, Pointer: &pointed} + compositePointer := NewAt(TypeOf(compositeValue), unsafe.Pointer(&compositeValue)) + compositePointer.Elem().Field(0).SetInt(23) + if compositeValue.Value != 23 { + t.Fatalf("NewAt struct field = %d, want 23", compositeValue.Value) + } + other := 2 + compositePointer.Elem().Field(1).Set(ValueOf(&other)) + if compositeValue.Pointer != &other { + t.Fatalf("NewAt pointer field = %p, want %p", compositeValue.Pointer, &other) + } + + nilValue := NewAt(TypeOf(value), nil) + if !nilValue.IsNil() { + t.Fatal("NewAt with nil pointer is not nil") + } + if nilValue.Elem().IsValid() { + t.Fatal("Elem of NewAt with nil pointer is valid") + } +} + func TestTinyMap(t *testing.T) { m := make(map[string]int)