fix: checks that value implements a binary type in type assert
This commit is contained in:
55
_test/issue-558.go
Normal file
55
_test/issue-558.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type readAutoCloser struct {
|
||||
r io.ReadCloser
|
||||
}
|
||||
|
||||
func (a readAutoCloser) Read(b []byte) (n int, err error) {
|
||||
if a.r == nil {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n, err = a.r.Read(b)
|
||||
if err == io.EOF {
|
||||
a.Close()
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (a readAutoCloser) Close() error {
|
||||
if a.r == nil {
|
||||
return nil
|
||||
}
|
||||
return a.r.(io.Closer).Close()
|
||||
}
|
||||
|
||||
type pipe struct {
|
||||
Reader readAutoCloser
|
||||
}
|
||||
|
||||
func newReadAutoCloser(r io.Reader) readAutoCloser {
|
||||
if _, ok := r.(io.Closer); !ok {
|
||||
return readAutoCloser{ioutil.NopCloser(r)}
|
||||
}
|
||||
return readAutoCloser{r.(io.ReadCloser)}
|
||||
}
|
||||
|
||||
func main() {
|
||||
p := &pipe{}
|
||||
p.Reader = newReadAutoCloser(strings.NewReader("test"))
|
||||
b, err := ioutil.ReadAll(p.Reader)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// test
|
||||
18
_test/type20.go
Normal file
18
_test/type20.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func isCloser(r io.Reader) bool {
|
||||
_, ok := r.(io.Closer)
|
||||
return ok
|
||||
}
|
||||
|
||||
func main() {
|
||||
println(isCloser(strings.NewReader("test")))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// false
|
||||
@@ -121,30 +121,33 @@ func runCfg(n *node, f *frame) {
|
||||
}
|
||||
|
||||
func typeAssertStatus(n *node) {
|
||||
value := genValue(n.child[0]) // input value
|
||||
c0, c1 := n.child[0], n.child[1]
|
||||
value := genValue(c0) // input value
|
||||
value1 := genValue(n.anc.child[1]) // returned status
|
||||
typ := c1.typ.rtype // type to assert
|
||||
next := getExec(n.tnext)
|
||||
|
||||
switch {
|
||||
case n.child[0].typ.cat == valueT:
|
||||
case c0.typ.cat == valueT:
|
||||
n.exec = func(f *frame) bltn {
|
||||
if !value(f).IsValid() || value(f).IsNil() {
|
||||
v := value(f)
|
||||
if !v.IsValid() || v.IsNil() {
|
||||
value1(f).SetBool(false)
|
||||
}
|
||||
value1(f).SetBool(true)
|
||||
value1(f).SetBool(v.Type().Implements(typ))
|
||||
return next
|
||||
}
|
||||
case n.child[1].typ.cat == interfaceT:
|
||||
case c1.typ.cat == interfaceT:
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, ok := value(f).Interface().(valueInterface)
|
||||
//value0(f).Set(reflect.ValueOf(valueInterface{v.node, v.value}))
|
||||
// TODO: verify that value(f) implements asserted type.
|
||||
value1(f).SetBool(ok)
|
||||
return next
|
||||
}
|
||||
default:
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, ok := value(f).Interface().(valueInterface)
|
||||
//value0(f).Set(v.value)
|
||||
// TODO: verify that value(f) implements asserted type.
|
||||
value1(f).SetBool(ok)
|
||||
return next
|
||||
}
|
||||
@@ -152,25 +155,29 @@ func typeAssertStatus(n *node) {
|
||||
}
|
||||
|
||||
func typeAssert(n *node) {
|
||||
value := genValue(n.child[0]) // input value
|
||||
dest := genValue(n) // returned result
|
||||
c0, c1 := n.child[0], n.child[1]
|
||||
value := genValue(c0) // input value
|
||||
dest := genValue(n) // returned result
|
||||
next := getExec(n.tnext)
|
||||
|
||||
switch {
|
||||
case n.child[0].typ.cat == valueT:
|
||||
case c0.typ.cat == valueT:
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(value(f).Elem())
|
||||
v := value(f)
|
||||
dest(f).Set(v.Elem())
|
||||
return next
|
||||
}
|
||||
case n.child[1].typ.cat == interfaceT:
|
||||
case c1.typ.cat == interfaceT:
|
||||
n.exec = func(f *frame) bltn {
|
||||
v := value(f).Interface().(valueInterface)
|
||||
// TODO: verify that value(f) implements asserted type.
|
||||
dest(f).Set(reflect.ValueOf(valueInterface{v.node, v.value}))
|
||||
return next
|
||||
}
|
||||
default:
|
||||
n.exec = func(f *frame) bltn {
|
||||
v := value(f).Interface().(valueInterface)
|
||||
// TODO: verify that value(f) implements asserted type.
|
||||
dest(f).Set(v.value)
|
||||
return next
|
||||
}
|
||||
@@ -195,6 +202,7 @@ func typeAssert2(n *node) {
|
||||
case n.child[1].typ.cat == interfaceT:
|
||||
n.exec = func(f *frame) bltn {
|
||||
v, ok := value(f).Interface().(valueInterface)
|
||||
// TODO: verify that value(f) implements asserted type.
|
||||
value0(f).Set(reflect.ValueOf(valueInterface{v.node, v.value}))
|
||||
value1(f).SetBool(ok)
|
||||
return next
|
||||
@@ -202,6 +210,7 @@ func typeAssert2(n *node) {
|
||||
default:
|
||||
n.exec = func(f *frame) bltn {
|
||||
v, ok := value(f).Interface().(valueInterface)
|
||||
// TODO: verify that value(f) implements asserted type.
|
||||
value0(f).Set(v.value)
|
||||
value1(f).SetBool(ok)
|
||||
return next
|
||||
|
||||
Reference in New Issue
Block a user