This patch to libgo is a copy of a patch I recently made to the master Go library. This changes the reflect package to allocate memory using the correct types for interface conversions. The code was incorrectly allocating an empty interface type to hold a non-empty interface value. This was working in the master library because it coincidentally always handled the values correctly. This was working in gccgo because we almost never have the types anyhow, although we plan to change that shortly. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 87f8de53800a libgo/go/reflect/value.go --- a/libgo/go/reflect/value.go Fri Oct 17 17:41:04 2014 -0700 +++ b/libgo/go/reflect/value.go Mon Oct 20 10:59:43 2014 -0700 @@ -1405,9 +1405,9 @@ func (v Value) Set(x Value) { v.mustBeAssignable() x.mustBeExported() // do not let unexported x leak - var target *interface{} + var target unsafe.Pointer if v.kind() == Interface { - target = (*interface{})(v.ptr) + target = v.ptr } x = x.assignTo("reflect.Set", v.typ, target) if x.flag&flagIndir != 0 { @@ -2230,7 +2230,7 @@ // assignTo returns a value v that can be assigned directly to typ. // It panics if v is not assignable to typ. // For a conversion to an interface type, target is a suggested scratch space to use. -func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value { +func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value { if v.flag&flagMethod != 0 { v = makeMethodValue(context, v) } @@ -2246,15 +2246,15 @@ case implements(dst, v.typ): if target == nil { - target = new(interface{}) + target = unsafe_New(dst) } x := valueInterface(v, false) if dst.NumMethod() == 0 { - *target = x + *(*interface{})(target) = x } else { - ifaceE2I(dst, x, unsafe.Pointer(target)) + ifaceE2I(dst, x, target) } - return Value{dst, unsafe.Pointer(target) /* 0, */, flagIndir | flag(Interface)<<flagKindShift} + return Value{dst, target /* 0, */, flagIndir | flag(Interface)<<flagKindShift} } // Failed. @@ -2537,14 +2537,14 @@ // convertOp: concrete -> interface func cvtT2I(v Value, typ Type) Value { - target := new(interface{}) + target := unsafe_New(typ.common()) x := valueInterface(v, false) if typ.NumMethod() == 0 { - *target = x + *(*interface{})(target) = x } else { - ifaceE2I(typ.(*rtype), x, unsafe.Pointer(target)) + ifaceE2I(typ.(*rtype), x, target) } - return Value{typ.common(), unsafe.Pointer(target) /* 0, */, v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift} + return Value{typ.common(), target /* 0, */, v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift} } // convertOp: interface -> interface