diff --git a/internal/lib/reflect/type.go b/internal/lib/reflect/type.go index fbc89ecc..660d5639 100644 --- a/internal/lib/reflect/type.go +++ b/internal/lib/reflect/type.go @@ -642,58 +642,43 @@ func (t *rtype) NumField() int { } func (t *rtype) In(i int) Type { - /* - if t.Kind() != Func { - panic("reflect: In of non-func type " + t.String()) - } - tt := (*abi.FuncType)(unsafe.Pointer(t)) - return toType(tt.InSlice()[i]) - */ - panic("todo: reflect.rtype.In") + if t.Kind() != Func { + panic("reflect: In of non-func type " + t.String()) + } + tt := (*abi.FuncType)(unsafe.Pointer(t)) + return toType(tt.In[i]) } func (t *rtype) NumIn() int { - /* - if t.Kind() != Func { - panic("reflect: NumIn of non-func type " + t.String()) - } - tt := (*abi.FuncType)(unsafe.Pointer(t)) - return tt.NumIn() - */ - panic("todo: reflect.rtype.NumIn") + if t.Kind() != Func { + panic("reflect: NumIn of non-func type " + t.String()) + } + tt := (*abi.FuncType)(unsafe.Pointer(t)) + return len(tt.In) } func (t *rtype) NumOut() int { - /* - if t.Kind() != Func { - panic("reflect: NumOut of non-func type " + t.String()) - } - tt := (*abi.FuncType)(unsafe.Pointer(t)) - return tt.NumOut() - */ - panic("todo: reflect.rtype.NumOut") + if t.Kind() != Func { + panic("reflect: NumOut of non-func type " + t.String()) + } + tt := (*abi.FuncType)(unsafe.Pointer(t)) + return len(tt.Out) } func (t *rtype) Out(i int) Type { - /* - if t.Kind() != Func { - panic("reflect: Out of non-func type " + t.String()) - } - tt := (*abi.FuncType)(unsafe.Pointer(t)) - return toType(tt.OutSlice()[i]) - */ - panic("todo: reflect.rtype.Out") + if t.Kind() != Func { + panic("reflect: Out of non-func type " + t.String()) + } + tt := (*abi.FuncType)(unsafe.Pointer(t)) + return toType(tt.Out[i]) } func (t *rtype) IsVariadic() bool { - /* - if t.Kind() != Func { - panic("reflect: IsVariadic of non-func type " + t.String()) - } - tt := (*abi.FuncType)(unsafe.Pointer(t)) - return tt.IsVariadic() - */ - panic("todo: reflect.rtype.IsVariadic") + if t.Kind() != Func { + panic("reflect: IsVariadic of non-func type " + t.String()) + } + tt := (*abi.FuncType)(unsafe.Pointer(t)) + return tt.Variadic() } // add returns p+x. diff --git a/internal/lib/reflect/value.go b/internal/lib/reflect/value.go index 0a09ae3a..daaa669e 100644 --- a/internal/lib/reflect/value.go +++ b/internal/lib/reflect/value.go @@ -183,9 +183,6 @@ func unpackEface(i any) Value { } if t.TFlag&abi.TFlagClosure != 0 { f = (f & flag(^Struct)) | flag(Func) | flagClosure - ft := *t.StructType().Fields[0].Typ.FuncType() - ft.In = ft.In[1:] - t = &ft.Type } return Value{t, e.word, f} } @@ -1528,7 +1525,7 @@ func (v Value) TrySend(x Value) bool { // Type returns v's type. func (v Value) Type() Type { - if v.flag != 0 && v.flag&flagMethod == 0 { + if v.flag != 0 && v.flag&flagMethod == 0 && v.flag&flagClosure == 0 { return (*rtype)(unsafe.Pointer(v.typ_)) // inline of toRType(v.typ()), for own inlining in inline test } return v.typeSlow() @@ -1539,6 +1536,11 @@ func (v Value) typeSlow() Type { panic(&ValueError{"reflect.Value.Type", Invalid}) } + // closure func + if v.flag&flagClosure != 0 { + return toRType(&v.funcType().Type) + } + typ := v.typ() if v.flag&flagMethod == 0 { return toRType(v.typ()) @@ -2081,6 +2083,16 @@ func toFFISig(typ *abi.FuncType, closure bool) (*ffi.Signature, error) { return ffi.NewSignature(ret, args...) } +func (v Value) funcType() *abi.FuncType { + if v.flag&flagClosure != 0 { + t := v.typ() + ft := *t.StructType().Fields[0].Typ.FuncType() + ft.In = ft.In[1:] + return &ft + } + return v.typ().FuncType() +} + func (v Value) call(op string, in []Value) (out []Value) { var ( fn unsafe.Pointer @@ -2098,7 +2110,7 @@ func (v Value) call(op string, in []Value) (out []Value) { fn = v.ptr } } - ft := v.typ().FuncType() + ft := v.funcType() sig, err := toFFISig(ft, v.flag&flagClosure != 0) if err != nil { panic(err)