interp: fix use of interfaces in composite types

The representation of non empty interfaces defined in the interpreter is now identical between refType() and frameType() functions, which are used to generate interpreter objects.

Fixes #1447 and #1426.
This commit is contained in:
Marc Vertes
2022-09-01 12:18:08 +02:00
committed by GitHub
parent 03ccda1a69
commit 63825e7201
6 changed files with 58 additions and 38 deletions

View File

@@ -1817,8 +1817,9 @@ func exportName(s string) string {
var (
// TODO(mpl): generators.
interf = reflect.TypeOf((*interface{})(nil)).Elem()
constVal = reflect.TypeOf((*constant.Value)(nil)).Elem()
emptyInterfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
valueInterfaceType = reflect.TypeOf((*valueInterface)(nil)).Elem()
constVal = reflect.TypeOf((*constant.Value)(nil)).Elem()
)
type fieldRebuild struct {
@@ -1971,7 +1972,12 @@ func (t *itype) refType(ctx *refTypeContext) reflect.Type {
}
t.rtype = reflect.FuncOf(in, out, variadic)
case interfaceT:
t.rtype = interf
if len(t.field) == 0 {
// empty interface, do not wrap it
t.rtype = emptyInterfaceType
break
}
t.rtype = valueInterfaceType
case mapT:
t.rtype = reflect.MapOf(t.key.refType(ctx), t.val.refType(ctx))
case ptrT:
@@ -2056,10 +2062,10 @@ func (t *itype) frameType() (r reflect.Type) {
case interfaceT:
if len(t.field) == 0 {
// empty interface, do not wrap it
r = reflect.TypeOf((*interface{})(nil)).Elem()
r = emptyInterfaceType
break
}
r = reflect.TypeOf((*valueInterface)(nil)).Elem()
r = valueInterfaceType
case mapT:
r = reflect.MapOf(t.key.frameType(), t.val.frameType())
case ptrT:
@@ -2072,6 +2078,14 @@ func (t *itype) frameType() (r reflect.Type) {
func (t *itype) implements(it *itype) bool {
if isBin(t) {
// Note: in case of a valueInterfaceType, we
// miss required data which will be available
// later, so we optimistically return true to progress,
// and additional checks will be hopefully performed at
// runtime.
if rt := it.TypeOf(); rt == valueInterfaceType {
return true
}
return t.TypeOf().Implements(it.TypeOf())
}
return t.methods().contains(it.methods())
@@ -2127,11 +2141,15 @@ func (t *itype) defaultType(v reflect.Value, sc *scope) *itype {
func (t *itype) isNil() bool { return t.cat == nilT }
func (t *itype) hasNil() bool {
switch t.TypeOf().Kind() {
switch rt := t.TypeOf(); rt.Kind() {
case reflect.UnsafePointer:
return true
case reflect.Slice, reflect.Ptr, reflect.Func, reflect.Interface, reflect.Map, reflect.Chan:
return true
case reflect.Struct:
if rt == valueInterfaceType {
return true
}
}
return false
}
@@ -2246,7 +2264,7 @@ func isInterfaceBin(t *itype) bool {
}
func isInterface(t *itype) bool {
return isInterfaceSrc(t) || t.TypeOf() != nil && t.TypeOf().Kind() == reflect.Interface
return isInterfaceSrc(t) || t.TypeOf() == valueInterfaceType || t.TypeOf() != nil && t.TypeOf().Kind() == reflect.Interface
}
func isBin(t *itype) bool {