mirror of
https://github.com/golang/go
synced 2024-11-12 06:30:21 -07:00
reflect: fix variadic arg for funcs created by MakeFunc.
Short circuit for calling values funcs by MakeFunc was placed before variadic arg rearrangement code in reflect.call. Fixes #7534. LGTM=khr R=golang-codereviews, bradfitz, khr, rsc CC=golang-codereviews https://golang.org/cl/75370043
This commit is contained in:
parent
89e128dd76
commit
772d22885b
@ -1512,6 +1512,23 @@ func TestMakeFuncInterface(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMakeFuncVariadic(t *testing.T) {
|
||||||
|
// Test that variadic arguments are packed into a slice and passed as last arg
|
||||||
|
fn := func(_ int, is ...int) []int { return nil }
|
||||||
|
fv := MakeFunc(TypeOf(fn), func(in []Value) []Value { return in[1:2] })
|
||||||
|
ValueOf(&fn).Elem().Set(fv)
|
||||||
|
|
||||||
|
r := fv.Call([]Value{ValueOf(1), ValueOf(2), ValueOf(3)})[0].Interface().([]int)
|
||||||
|
if r[0] != 2 || r[1] != 3 {
|
||||||
|
t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
r = fv.CallSlice([]Value{ValueOf(1), ValueOf([]int{2, 3})})[0].Interface().([]int)
|
||||||
|
if r[0] != 2 || r[1] != 3 {
|
||||||
|
t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Point struct {
|
type Point struct {
|
||||||
x, y int
|
x, y int
|
||||||
}
|
}
|
||||||
|
@ -453,17 +453,6 @@ func (v Value) call(op string, in []Value) []Value {
|
|||||||
panic("reflect.Value.Call: call of nil function")
|
panic("reflect.Value.Call: call of nil function")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If target is makeFuncStub, short circuit the unpack onto stack /
|
|
||||||
// pack back into []Value for the args and return values. Just do the
|
|
||||||
// call directly.
|
|
||||||
// We need to do this here because otherwise we have a situation where
|
|
||||||
// reflect.callXX calls makeFuncStub, neither of which knows the
|
|
||||||
// layout of the args. That's bad for precise gc & stack copying.
|
|
||||||
x := (*makeFuncImpl)(fn)
|
|
||||||
if x.code == makeFuncStubCode {
|
|
||||||
return x.fn(in)
|
|
||||||
}
|
|
||||||
|
|
||||||
isSlice := op == "CallSlice"
|
isSlice := op == "CallSlice"
|
||||||
n := t.NumIn()
|
n := t.NumIn()
|
||||||
if isSlice {
|
if isSlice {
|
||||||
@ -521,6 +510,17 @@ func (v Value) call(op string, in []Value) []Value {
|
|||||||
}
|
}
|
||||||
nout := t.NumOut()
|
nout := t.NumOut()
|
||||||
|
|
||||||
|
// If target is makeFuncStub, short circuit the unpack onto stack /
|
||||||
|
// pack back into []Value for the args and return values. Just do the
|
||||||
|
// call directly.
|
||||||
|
// We need to do this here because otherwise we have a situation where
|
||||||
|
// reflect.callXX calls makeFuncStub, neither of which knows the
|
||||||
|
// layout of the args. That's bad for precise gc & stack copying.
|
||||||
|
x := (*makeFuncImpl)(fn)
|
||||||
|
if x.code == makeFuncStubCode {
|
||||||
|
return x.fn(in)
|
||||||
|
}
|
||||||
|
|
||||||
// If the target is methodValueCall, do its work here: add the receiver
|
// If the target is methodValueCall, do its work here: add the receiver
|
||||||
// argument and call the real target directly.
|
// argument and call the real target directly.
|
||||||
// We need to do this here because otherwise we have a situation where
|
// We need to do this here because otherwise we have a situation where
|
||||||
|
Loading…
Reference in New Issue
Block a user