}
}
+ struct StructTest : IFaceTest {
+
+ int i;
+
+ public StructTest (int arg) {
+ i = arg;
+ }
+
+ public int iface_method () {
+ return i;
+ }
+ }
+
// Test constrained calls on an interface made from gsharedvt methods
public static int test_42_gsharedvt_constrained_iface () {
IFaceConstrainedIFace obj = new ConstrainedIFace ();
return obj.foo<IFaceTest, int> (ref t);
}
+ public static int test_42_gsharedvt_constrained_iface_vtype () {
+ IFaceConstrainedIFace obj = new ConstrainedIFace ();
+ IFaceTest t = new StructTest (42);
+ return obj.foo<IFaceTest, int> (ref t);
+ }
+
// Sign extension tests
// 0x55 == 85 == 01010101
// 0xAA == 170 == 10101010
{
MonoMethod *m;
int vt_slot, iface_offset;
+ gboolean is_iface = FALSE;
error_init (error);
if (mono_class_is_interface (klass)) {
MonoObject *this_obj;
+ is_iface = TRUE;
+
/* Have to use the receiver's type instead of klass, the receiver is a ref type */
this_obj = *(MonoObject**)mp;
g_assert (this_obj);
m = mono_class_inflate_generic_method (m, mono_method_get_context (cmethod));
}
- if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class))
+ if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class)) {
/*
* Calling a non-vtype method with a vtype receiver, has to box.
*/
*this_arg = mono_value_box_checked (mono_domain_get (), klass, mp, error);
- else if (klass->valuetype)
- /*
- * Calling a vtype method with a vtype receiver
- */
- *this_arg = mp;
- else
+ } else if (klass->valuetype) {
+ if (is_iface) {
+ /*
+ * The original type is an interface, so the receiver is a ref,
+ the called method is a vtype method, need to unbox.
+ */
+ MonoObject *this_obj = *(MonoObject**)mp;
+
+ *this_arg = mono_object_unbox (this_obj);
+ } else {
+ /*
+ * Calling a vtype method with a vtype receiver
+ */
+ *this_arg = mp;
+ }
+ } else {
/*
* Calling a non-vtype method
*/
*this_arg = *(gpointer*)mp;
+ }
+
return m;
}