Make delegate-invoke wrappers for generic delegates like Func/Action generic, i.e...
[mono.git] / mono / metadata / class.c
index bef40e06e5ac208f7320a5ff7cc381476fbff47f..b0a4d3579a649774bedc5accd7624c8af8e3d9a6 100644 (file)
@@ -67,11 +67,77 @@ static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token
 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
 static guint32 mono_field_resolve_flags (MonoClassField *field);
 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
+static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
 
 
 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
 void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass) = NULL;
 
+
+/*
+We use gclass recording to allow recursive system f types to be referenced by a parent.
+
+Given the following type hierarchy:
+
+class TextBox : TextBoxBase<TextBox> {}
+class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
+class TextInput<T> : Input<T> where T: TextInput<T> {}
+class Input<T> {}
+
+The runtime tries to load TextBoxBase<>.
+To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
+To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
+To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
+
+At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded 
+at this point, iow, both are registered in the type map and both and a NULL parent. This means
+that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
+
+To fix that what we do is to record all generic instantes created while resolving the parent of
+any generic type definition and, after resolved, correct the parent field if needed.
+
+*/
+static int record_gclass_instantiation;
+static GSList *gclass_recorded_list;
+typedef gboolean (*gclass_record_func) (MonoClass*, void*);
+
+/* 
+ * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
+*/
+static void
+enable_gclass_recording (void)
+{
+       ++record_gclass_instantiation;
+}
+
+/* 
+ * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
+*/
+static void
+disable_gclass_recording (gclass_record_func func, void *user_data)
+{
+       GSList **head = &gclass_recorded_list;
+
+       g_assert (record_gclass_instantiation > 0);
+       --record_gclass_instantiation;
+
+       while (*head) {
+               GSList *node = *head;
+               if (func ((MonoClass*)node->data, user_data)) {
+                       *head = node->next;
+                       g_slist_free_1 (node);
+               } else {
+                       head = &node->next;
+               }
+       }
+
+       /* We automatically discard all recorded gclasses when disabled. */
+       if (!record_gclass_instantiation && gclass_recorded_list) {
+               g_slist_free (gclass_recorded_list);
+               gclass_recorded_list = NULL;
+       }
+}
+
 /*
  * mono_class_from_typeref:
  * @image: a MonoImage
@@ -513,6 +579,21 @@ mono_class_is_open_constructed_type (MonoType *t)
        }
 }
 
+/*
+This is a simple function to catch the most common bad instances of generic types.
+Specially those that might lead to further failures in the runtime.
+*/
+static gboolean
+is_valid_generic_argument (MonoType *type)
+{
+       switch (type->type) {
+       case MONO_TYPE_VOID:
+       //case MONO_TYPE_TYPEDBYREF:
+               return FALSE;
+       }
+       return TRUE;
+}
+
 static MonoType*
 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
 {
@@ -532,6 +613,12 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
                        return NULL;
                }
 
+               if (!is_valid_generic_argument (inst->type_argv [num])) {
+                       MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
+                       mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
+                               num, info ? info->name : "", inst->type_argv [num]->type);
+                       return NULL;                    
+               }
                /*
                 * Note that the VAR/MVAR cases are different from the rest.  The other cases duplicate @type,
                 * while the VAR/MVAR duplicates a type from the context.  So, we need to ensure that the
@@ -554,6 +641,12 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
                                num, info ? info->name : "", inst->type_argc);
                        return NULL;
                }
+               if (!is_valid_generic_argument (inst->type_argv [num])) {
+                       MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
+                       mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
+                               num, info ? info->name : "", inst->type_argv [num]->type);
+                       return NULL;                    
+               }
                nt = mono_metadata_type_dup (image, inst->type_argv [num]);
                nt->byref = type->byref;
                nt->attrs = type->attrs;
@@ -1328,7 +1421,7 @@ mono_class_setup_fields (MonoClass *class)
        MonoGenericContainer *container = NULL;
        MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
 
-       if (class->size_inited)
+       if (class->setup_fields_called)
                return;
 
        if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
@@ -1401,9 +1494,9 @@ mono_class_setup_fields (MonoClass *class)
                if (explicit_size && real_size) {
                        class->instance_size = MAX (real_size, class->instance_size);
                }
-               class->size_inited = 1;
                class->blittable = blittable;
                mono_memory_barrier ();
+               class->size_inited = 1;
                class->fields_inited = 1;
                return;
        }
@@ -1412,7 +1505,7 @@ mono_class_setup_fields (MonoClass *class)
                blittable = FALSE;
 
        /* Prevent infinite loops if the class references itself */
-       class->size_inited = 1;
+       class->setup_fields_called = 1;
 
        if (class->generic_container) {
                container = class->generic_container;
@@ -1620,7 +1713,7 @@ mono_class_layout_fields (MonoClass *class)
         */
         /* corlib is missing [StructLayout] directives in many places */
        if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
-               if (class->byval_arg.type != MONO_TYPE_VALUETYPE)
+               if (!class->valuetype)
                        gc_aware_layout = TRUE;
        }
 
@@ -1818,6 +1911,7 @@ mono_class_layout_fields (MonoClass *class)
                        class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
        }
 
+       mono_memory_barrier ();
        class->size_inited = 1;
 
        /*
@@ -2714,9 +2808,11 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
        static MonoClass* generic_icollection_class = NULL;
        static MonoClass* generic_ienumerable_class = NULL;
        static MonoClass* generic_ienumerator_class = NULL;
+       static MonoClass* generic_ireadonlylist_class = NULL;
+       static MonoClass* generic_ireadonlycollection_class = NULL;
        MonoClass *valuetype_types[2] = { NULL, NULL };
        MonoClass **interfaces = NULL;
-       int i, interface_count, real_count, original_rank;
+       int i, nifaces, interface_count, real_count, original_rank;
        int all_interfaces;
        gboolean internal_enumerator;
        gboolean eclass_is_valuetype;
@@ -2758,6 +2854,10 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
                        "System.Collections.Generic", "IEnumerable`1");
                generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "IEnumerator`1");
+               generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
+                       "System.Collections.Generic", "IReadOnlyList`1");
+               generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
+                       "System.Collections.Generic", "IReadOnlyCollection`1");
        }
 
        mono_class_init (eclass);
@@ -2765,15 +2865,17 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
        /*
         * Arrays in 2.0 need to implement a number of generic interfaces
         * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
-        * on the element class). We collect the types needed to build the
-        * instantiations in interfaces at intervals of 3, because 3 are
+        * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
+        * We collect the types needed to build the
+        * instantiations in interfaces at intervals of 3/5, because 3/5 are
         * the generic interfaces needed to implement.
         */
+       nifaces = generic_ireadonlylist_class ? 5 : 3;
        if (eclass->valuetype) {
                fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
 
-               /* IList, ICollection, IEnumerable */
-               real_count = interface_count = valuetype_types [1] ? 6 : 3;
+               /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
+               real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
                if (internal_enumerator) {
                        ++real_count;
                        if (valuetype_types [1])
@@ -2783,7 +2885,7 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
                interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
                interfaces [0] = valuetype_types [0];
                if (valuetype_types [1])
-                       interfaces [3] = valuetype_types [1];
+                       interfaces [nifaces] = valuetype_types [1];
 
                eclass_is_valuetype = TRUE;
        } else {
@@ -2811,8 +2913,8 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
                        if (valuetype_types [1])
                                ++interface_count;
                }
-               /* IList, ICollection, IEnumerable */
-               interface_count *= 3;
+               /* IList, ICollection, IEnumerable, IReadOnlyList */
+               interface_count *= nifaces;
                real_count = interface_count;
                if (internal_enumerator) {
                        real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
@@ -2822,39 +2924,43 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
                interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
                if (MONO_CLASS_IS_INTERFACE (eclass)) {
                        interfaces [0] = mono_defaults.object_class;
-                       j = 3;
+                       j = nifaces;
                } else {
                        j = 0;
                        for (i = 0; i < idepth; i++) {
                                mono_class_init (eclass->supertypes [i]);
                                interfaces [j] = eclass->supertypes [i];
-                               j += 3;
+                               j += nifaces;
                        }
                }
                if (all_interfaces) {
                        for (i = 0; i < eclass->interface_offsets_count; i++) {
                                interfaces [j] = eclass->interfaces_packed [i];
-                               j += 3;
+                               j += nifaces;
                        }
                } else {
                        for (i = 0; i < eclass->interface_count; i++) {
                                interfaces [j] = eclass->interfaces [i];
-                               j += 3;
+                               j += nifaces;
                        }
                }
                if (valuetype_types [1]) {
                        interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
-                       j += 3;
+                       j += nifaces;
                }
        }
 
        /* instantiate the generic interfaces */
-       for (i = 0; i < interface_count; i += 3) {
+       for (i = 0; i < interface_count; i += nifaces) {
                MonoClass *iface = interfaces [i];
 
                interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
                interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
                interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
+               if (generic_ireadonlylist_class) {
+                       interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
+                       interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
+               }
        }
        if (internal_enumerator) {
                int j;
@@ -3246,14 +3352,19 @@ setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
                                /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/
                        }
                } else {
-                       int ilist_offset, icollection_offset, ienumerable_offset;
+                       int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
                        int ilist_iface_idx = find_array_interface (class, "IList`1");
                        MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
+                       int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
+                       MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
                        int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
                        int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
+                       int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
                        ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
                        icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
                        ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
+                       ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
+                       ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
                        g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
                        for (i = 0; i < num_array_interfaces; ++i) {
                                int offset;
@@ -3264,6 +3375,10 @@ setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
                                        offset = icollection_offset;
                                else if (strcmp (ic->name, "IEnumerable`1") == 0)
                                        offset = ienumerable_offset;
+                               else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
+                                       offset = ireadonlylist_offset;
+                               else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
+                                       offset = ireadonlycollection_offset;
                                else
                                        g_assert_not_reached ();
                                set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
@@ -3672,7 +3787,7 @@ check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *c
                        TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
                        return FALSE;
                }
-               if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0))) {
+               if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0) && (strcmp (ic_name, "IReadOnlyList`1") != 0) && (strcmp (ic_name, "IReadOnlyCollection`1") != 0))) {
                        TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
                        return FALSE;
                }
@@ -4496,6 +4611,23 @@ mono_method_get_vtable_slot (MonoMethod *method)
                mono_class_setup_vtable (method->klass);
                if (method->klass->exception_type)
                        return -1;
+               if (method->slot == -1) {
+                       MonoClass *gklass;
+                       int i;
+
+                       /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
+                       g_assert (method->klass->generic_class);
+                       gklass = method->klass->generic_class->container_class;
+                       mono_class_setup_methods (method->klass);
+                       g_assert (method->klass->methods);
+                       for (i = 0; i < method->klass->method.count; ++i) {
+                               if (method->klass->methods [i] == method)
+                                       break;
+                       }
+                       g_assert (i < method->klass->method.count);
+                       g_assert (gklass->methods);
+                       method->slot = gklass->methods [i]->slot;
+               }
                g_assert (method->slot != -1);
        }
        return method->slot;
@@ -4583,6 +4715,9 @@ generic_array_methods (MonoClass *class)
                const char *mname, *iname;
                gchar *name;
                MonoMethod *m = tmp->data;
+               const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
+               const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
+
                generic_array_method_info [i].array_method = m;
                if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
                        iname = "System.Collections.Generic.ICollection`1.";
@@ -4590,6 +4725,12 @@ generic_array_methods (MonoClass *class)
                } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
                        iname = "System.Collections.Generic.IEnumerable`1.";
                        mname = m->name + 27;
+               } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
+                       iname = "System.Collections.Generic.IReadOnlyList`1.";
+                       mname = m->name + strlen (ireadonlylist_prefix);
+               } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
+                       iname = "System.Collections.Generic.IReadOnlyCollection`1.";
+                       mname = m->name + strlen (ireadonlycollection_prefix);
                } else if (!strncmp (m->name, "InternalArray__", 15)) {
                        iname = "System.Collections.Generic.IList`1.";
                        mname = m->name + 15;
@@ -5162,6 +5303,7 @@ mono_class_setup_mono_type (MonoClass *class)
 
 }
 
+#ifndef DISABLE_COM
 /*
  * COM initialization (using mono_init_com_types) is delayed until needed. 
  * However when a [ComImport] attribute is present on a type it will trigger
@@ -5185,6 +5327,7 @@ init_com_from_comimport (MonoClass *class)
        /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
        mono_init_com_types ();
 }
+#endif /*DISABLE_COM*/
 
 /*
  * LOCKING: this assumes the loader lock is held
@@ -5211,11 +5354,13 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
 
        if (!MONO_CLASS_IS_INTERFACE (class)) {
                /* Imported COM Objects always derive from __ComObject. */
+#ifndef DISABLE_COM
                if (MONO_CLASS_IS_IMPORT (class)) {
                        init_com_from_comimport (class);
                        if (parent == mono_defaults.object_class)
                                parent = mono_defaults.com_object_class;
                }
+#endif
                if (!parent) {
                        /* set the parent to something useful and safe, but mark the type as broken */
                        parent = mono_defaults.object_class;
@@ -5261,8 +5406,10 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                /*class->enumtype = class->parent->enumtype; */
        } else {
                /* initialize com types if COM interfaces are present */
+#ifndef DISABLE_COM
                if (MONO_CLASS_IS_IMPORT (class))
                        init_com_from_comimport (class);
+#endif
                class->parent = NULL;
        }
 
@@ -5310,6 +5457,21 @@ mono_class_setup_supertypes (MonoClass *class)
        mono_atomic_store_release (&class->supertypes, supertypes);
 }
 
+static gboolean
+fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
+{
+       MonoClass *gtd = (MonoClass*)user_data;
+       /* Only try to fix generic instances of @gtd */
+       if (gclass->generic_class->container_class != gtd)
+               return FALSE;
+
+       /* Check if the generic instance has no parent. */
+       if (gtd->parent && !gclass->parent)
+               mono_generic_class_setup_parent (gclass, gtd);
+
+       return TRUE;
+}
+
 /**
  * mono_class_create_from_typedef:
  * @image: image where the token is valid
@@ -5375,6 +5537,9 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                context = &class->generic_container->context;
        }
 
+       if (class->generic_container)
+               enable_gclass_recording ();
+
        if (cols [MONO_TYPEDEF_EXTENDS]) {
                MonoClass *tmp;
                guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
@@ -5412,6 +5577,9 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
        mono_class_setup_mono_type (class);
 
+       if (class->generic_container)
+               disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
+
        /* 
         * This might access class->byval_arg for recursion generated by generic constraints,
         * so it has to come after setup_mono_type ().
@@ -5548,6 +5716,31 @@ mono_class_get_nullable_param (MonoClass *klass)
        return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
 }
 
+static void
+mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
+{
+       if (gtd->parent) {
+               MonoError error;
+               MonoGenericClass *gclass = klass->generic_class;
+
+               klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
+               if (!mono_error_ok (&error)) {
+                       /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
+                       klass->parent = mono_defaults.object_class;
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       mono_error_cleanup (&error);
+               }
+       }
+       if (klass->parent)
+               mono_class_setup_parent (klass, klass->parent);
+
+       if (klass->enumtype) {
+               klass->cast_class = gtd->cast_class;
+               klass->element_class = gtd->element_class;
+       }
+}
+
+
 /*
  * Create the `MonoClass' for an instantiation of a generic type.
  * We only do this if we actually need it.
@@ -5570,6 +5763,9 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
 
        gklass = gclass->container_class;
 
+       if (record_gclass_instantiation > 0)
+               gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
+
        if (gklass->nested_in) {
                /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
                klass->nested_in = gklass->nested_in;
@@ -5604,24 +5800,7 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
         * We use the generic type definition to look for nested classes.
         */
 
-       if (gklass->parent) {
-               MonoError error;
-               klass->parent = mono_class_inflate_generic_class_checked (gklass->parent, mono_generic_class_get_context (gclass), &error);
-               if (!mono_error_ok (&error)) {
-                       /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
-                       klass->parent = mono_defaults.object_class;
-                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
-                       mono_error_cleanup (&error);
-               }
-       }
-
-       if (klass->parent)
-               mono_class_setup_parent (klass, klass->parent);
-
-       if (klass->enumtype) {
-               klass->cast_class = gklass->cast_class;
-               klass->element_class = gklass->element_class;
-       }
+       mono_generic_class_setup_parent (klass, gklass);
 
        if (gclass->is_dynamic) {
                klass->inited = 1;
@@ -5636,6 +5815,7 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
                         */
                        klass->instance_size = gklass->instance_size;
                        klass->sizes.class_size = gklass->sizes.class_size;
+                       mono_memory_barrier ();
                        klass->size_inited = 1;
                }
        }
@@ -5728,6 +5908,7 @@ make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is
        /*Init these fields to sane values*/
        klass->min_align = 1;
        klass->instance_size = sizeof (gpointer);
+       mono_memory_barrier ();
        klass->size_inited = 1;
 
        mono_class_setup_supertypes (klass);
@@ -9666,16 +9847,19 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
                return;
        }
 
-       if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY && mono_defaults.generic_ilist_class) {
+       if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
                MonoType *args [1];
 
                /* generic IList, ICollection, IEnumerable */
-               klass->interface_count = 1;
+               klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
                klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
 
                args [0] = &klass->element_class->byval_arg;
                klass->interfaces [0] = mono_class_bind_generic_parameters (
                        mono_defaults.generic_ilist_class, 1, args, FALSE);
+               if (klass->interface_count > 1)
+                       klass->interfaces [1] = mono_class_bind_generic_parameters (
+                          mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
        } else if (klass->generic_class) {
                MonoClass *gklass = klass->generic_class->container_class;
 
@@ -9755,8 +9939,13 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error)
                g_assert (*sig == 0x06);
                field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
                if (!field->type) {
+                       MonoLoaderError *lerror = mono_loader_get_last_error ();
+
                        mono_error_set_type_load_class (error, class, "Could not load field %s type", field->name);
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       if (lerror)
+                               set_failure_from_loader_error (class, lerror);
+                       else
+                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        mono_loader_clear_error ();
                }
        }
@@ -9838,3 +10027,10 @@ mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
        }
        return NULL;
 }
+
+char*
+mono_class_full_name (MonoClass *klass)
+{
+       return mono_type_full_name (&klass->byval_arg);
+}
+