interp: preserve concrete type when converting type to interface

This allows to fix the reassignment of an non empty interface value.
Before, reassignment was limited to empty interfaces.
    
Fixes #1138.
This commit is contained in:
Marc Vertes
2021-06-18 10:32:13 +02:00
committed by GitHub
parent 25c2a435f5
commit b2a11eaf2a
2 changed files with 16 additions and 3 deletions

View File

@@ -5,8 +5,18 @@ import (
"io"
)
type T struct {
r io.Reader
}
func (t *T) Read(p []byte) (n int, err error) { n, err = t.r.Read(p); return }
func main() {
x := io.LimitedReader{}
y := io.Reader(&x)
fmt.Println(y)
y = &T{y}
fmt.Println(y.Read([]byte("")))
}
// Output:
// 0 EOF

View File

@@ -930,9 +930,12 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
if !c1.typ.implements(c0.typ) {
err = n.cfgErrorf("type %v does not implement interface %v", c1.typ.id(), c0.typ.id())
}
// Pass value as is
// Convert type to interface while keeping a reference to the original concrete type.
// besides type, the node value remains preserved.
n.gen = nop
n.typ = c1.typ
t := *c0.typ
n.typ = &t
n.typ.val = c1.typ
n.findex = c1.findex
n.level = c1.level
n.val = c1.val