interp: fix creation of binary composite types (#1391)
* interp: fix creation of binary composite types Use direct assignment instead of reflect.Value Set method to initialize a binary composite type, as for non binary types. It ensures that a new reflect.Value is stored in the frame instead of modifying a possibly existing one, which can defeat the purpose of initializing variables in a body loop. While there, remove the need to have and use a mutex on types. Fixes #1381. * review: rework a bit the test Co-authored-by: mpl <mathieu.lonjaret@gmail.com>
This commit is contained in:
58
_test/issue-1381.go
Normal file
58
_test/issue-1381.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var bufPtrOne *bytes.Buffer
|
||||
var bufPtrTwo *bytes.Buffer
|
||||
var bufPtrThree *bytes.Buffer
|
||||
var bufPtrFour *bytes.Buffer
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
bufOne := bytes.Buffer{}
|
||||
bufTwo := &bytes.Buffer{}
|
||||
var bufThree bytes.Buffer
|
||||
bufFour := new(bytes.Buffer)
|
||||
|
||||
if bufPtrOne == nil {
|
||||
bufPtrOne = &bufOne
|
||||
} else if bufPtrOne == &bufOne {
|
||||
fmt.Println("bufOne was not properly redeclared")
|
||||
} else {
|
||||
fmt.Println("bufOne is properly redeclared")
|
||||
}
|
||||
|
||||
if bufPtrTwo == nil {
|
||||
bufPtrTwo = bufTwo
|
||||
} else if bufPtrTwo == bufTwo {
|
||||
fmt.Println("bufTwo was not properly redeclared")
|
||||
} else {
|
||||
fmt.Println("bufTwo is properly redeclared")
|
||||
}
|
||||
|
||||
if bufPtrThree == nil {
|
||||
bufPtrThree = &bufThree
|
||||
} else if bufPtrThree == &bufThree {
|
||||
fmt.Println("bufThree was not properly redeclared")
|
||||
} else {
|
||||
fmt.Println("bufThree is properly redeclared")
|
||||
}
|
||||
|
||||
if bufPtrFour == nil {
|
||||
bufPtrFour = bufFour
|
||||
} else if bufPtrFour == bufFour {
|
||||
fmt.Println("bufFour was not properly redeclared")
|
||||
} else {
|
||||
fmt.Println("bufFour is properly redeclared")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// bufOne is properly redeclared
|
||||
// bufTwo is properly redeclared
|
||||
// bufThree is properly redeclared
|
||||
// bufFour is properly redeclared
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// bltn type defines functions which run at CFG execution.
|
||||
@@ -2626,6 +2625,9 @@ func doCompositeBinStruct(n *node, hasType bool) {
|
||||
}
|
||||
}
|
||||
|
||||
frameIndex := n.findex
|
||||
l := n.level
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
s := reflect.New(typ).Elem()
|
||||
for i, v := range values {
|
||||
@@ -2636,7 +2638,7 @@ func doCompositeBinStruct(n *node, hasType bool) {
|
||||
case d.Kind() == reflect.Ptr:
|
||||
d.Set(s.Addr())
|
||||
default:
|
||||
d.Set(s)
|
||||
getFrame(f, l).data[frameIndex] = s
|
||||
}
|
||||
return next
|
||||
}
|
||||
@@ -2661,8 +2663,6 @@ func doComposite(n *node, hasType bool, keyed bool) {
|
||||
if typ.cat == ptrT || typ.cat == aliasT {
|
||||
typ = typ.val
|
||||
}
|
||||
var mu sync.Mutex
|
||||
typ.mu = &mu
|
||||
child := n.child
|
||||
if hasType {
|
||||
child = n.child[1:]
|
||||
@@ -2701,11 +2701,10 @@ func doComposite(n *node, hasType bool, keyed bool) {
|
||||
|
||||
frameIndex := n.findex
|
||||
l := n.level
|
||||
rt := typ.TypeOf()
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
typ.mu.Lock()
|
||||
// No need to call zero() as doComposite is only called for a structT.
|
||||
a := reflect.New(typ.TypeOf()).Elem()
|
||||
typ.mu.Unlock()
|
||||
a := reflect.New(rt).Elem()
|
||||
for i, v := range values {
|
||||
a.Field(i).Set(v(f))
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/traefik/yaegi/internal/unsafe2"
|
||||
)
|
||||
@@ -110,7 +109,6 @@ type structField struct {
|
||||
|
||||
// itype defines the internal representation of types in the interpreter.
|
||||
type itype struct {
|
||||
mu *sync.Mutex
|
||||
cat tcat // Type category
|
||||
field []structField // Array of struct fields if structT or interfaceT
|
||||
key *itype // Type of key element if MapT or nil
|
||||
|
||||
Reference in New Issue
Block a user