Merge pull request #2454 from tastywheattasteslikechicken/FixVtableAbort
[mono.git] / mono / metadata / class.c
index e9e693a1f5f2415b93b3447511eb3fe48b35ceab..d264ea32ba65bb24b09f9e54628227e7023f5d0f 100644 (file)
@@ -905,11 +905,7 @@ mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
        MonoError error;
        MonoType *result;
        result = mono_class_inflate_generic_type_checked (type, context, &error);
-
-       if (!mono_error_ok (&error)) {
-               mono_error_cleanup (&error);
-               return NULL;
-       }
+       mono_error_cleanup (&error);
        return result;
 }
 
@@ -955,6 +951,11 @@ mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoG
        return inflated;
 }
 
+/*
+ * mono_class_inflate_generic_class:
+ *
+ *   Inflate the class @gklass with @context. Set @error on failure.
+ */
 MonoClass*
 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
 {
@@ -969,24 +970,6 @@ mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext
 
        return res;
 }
-/*
- * mono_class_inflate_generic_class:
- *
- *   Inflate the class GKLASS with CONTEXT.
- */
-MonoClass*
-mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
-{
-       MonoError error;
-       MonoClass *res;
-
-       res = mono_class_inflate_generic_class_checked (gklass, context, &error);
-       g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
-
-       return res;
-}
-
-
 
 static MonoGenericContext
 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
@@ -1350,14 +1333,10 @@ mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
                        goto fail;
                }
 
-               ftype = mono_metadata_parse_type_full (m, container, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
-               if (!ftype) {
-                       if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
-                               mono_error_set_from_loader_error (error);
-                       else
-                               mono_error_set_bad_image (error, klass->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
+               ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
+               if (!ftype)
                        goto fail;
-               }
+
                if (klass->generic_class) {
                        //FIXME do we leak here?
                        ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
@@ -1385,11 +1364,11 @@ mono_type_has_exceptions (MonoType *type)
        case MONO_TYPE_CLASS:
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_SZARRAY:
-               return type->data.klass->exception_type;
+               return mono_class_has_failure (type->data.klass);
        case MONO_TYPE_ARRAY:
-               return type->data.array->eklass->exception_type;
+               return mono_class_has_failure (type->data.array->eklass);
        case MONO_TYPE_GENERICINST:
-               return mono_generic_class_get_class (type->data.generic_class)->exception_type;
+               return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
        default:
                return FALSE;
        }
@@ -1570,7 +1549,7 @@ mono_class_setup_fields (MonoClass *klass)
 
        if (gtd) {
                mono_class_setup_fields (gtd);
-               if (gtd->exception_type) {
+               if (mono_class_has_failure (gtd)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        return;
                }
@@ -1585,7 +1564,7 @@ mono_class_setup_fields (MonoClass *klass)
                mono_class_init (klass->parent);
                if (!klass->parent->size_inited) {
                        mono_class_setup_fields (klass->parent);
-                       if (klass->parent->exception_type) {
+                       if (mono_class_has_failure (klass->parent)) {
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                return;
                        }
@@ -1701,7 +1680,7 @@ mono_class_setup_fields (MonoClass *klass)
                                MonoClass *field_class = mono_class_from_mono_type (field->type);
                                if (field_class) {
                                        mono_class_setup_fields (field_class);
-                                       if (field_class->exception_type) {
+                                       if (mono_class_has_failure (field_class)) {
                                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                                break;
                                        }
@@ -1742,7 +1721,7 @@ mono_class_setup_fields (MonoClass *klass)
                klass->instance_size = MAX (real_size, klass->instance_size);
        }
 
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return;
        mono_class_layout_fields (klass);
 
@@ -1933,7 +1912,7 @@ mono_class_layout_fields (MonoClass *klass)
 
                if (klass->parent) {
                        mono_class_setup_fields (klass->parent);
-                       if (klass->parent->exception_type) {
+                       if (mono_class_has_failure (klass->parent)) {
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                return;
                        }
@@ -2191,9 +2170,9 @@ mono_class_setup_methods (MonoClass *klass)
                MonoClass *gklass = klass->generic_class->container_class;
 
                mono_class_init (gklass);
-               if (!gklass->exception_type)
+               if (!mono_class_has_failure (gklass))
                        mono_class_setup_methods (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        /* FIXME make exception_data less opaque so it's possible to dup it here */
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
                        return;
@@ -2374,7 +2353,7 @@ mono_class_get_method_by_index (MonoClass *klass, int index)
                return m;
        } else {
                mono_class_setup_methods (klass);
-               if (klass->exception_type) /*FIXME do proper error handling*/
+               if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
                        return NULL;
                g_assert (index >= 0 && index < klass->method.count);
                return klass->methods [index];
@@ -2396,7 +2375,7 @@ mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
        g_assert (method->klass == gklass);
 
        mono_class_setup_methods (gklass);
-       g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
+       g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
 
        for (i = 0; i < gklass->method.count; ++i) {
                if (gklass->methods [i] == method) {
@@ -2445,7 +2424,7 @@ mono_class_get_vtable_entry (MonoClass *klass, int offset)
                g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
        } else {
                mono_class_setup_vtable (klass);
-               if (klass->exception_type)
+               if (mono_class_has_failure (klass))
                        return NULL;
                m = klass->vtable [offset];
        }
@@ -2491,7 +2470,7 @@ mono_class_setup_properties (MonoClass *klass)
 
                mono_class_init (gklass);
                mono_class_setup_properties (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
                        return;
                }
@@ -2523,7 +2502,7 @@ mono_class_setup_properties (MonoClass *klass)
 
                if (count) {
                        mono_class_setup_methods (klass);
-                       if (klass->exception_type)
+                       if (mono_class_has_failure (klass))
                                return;
                }
 
@@ -2624,7 +2603,7 @@ mono_class_setup_events (MonoClass *klass)
                MonoGenericContext *context = NULL;
 
                mono_class_setup_events (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
                        return;
                }
@@ -2664,7 +2643,7 @@ mono_class_setup_events (MonoClass *klass)
 
                if (count) {
                        mono_class_setup_methods (klass);
-                       if (klass->exception_type) {
+                       if (mono_class_has_failure (klass)) {
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
                                return;
                        }
@@ -2863,7 +2842,7 @@ collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError
                        *res = g_ptr_array_new ();
                g_ptr_array_add (*res, ic);
                mono_class_init (ic);
-               if (ic->exception_type) {
+               if (mono_class_has_failure (ic)) {
                        mono_error_set_type_load_class (error, ic, "Error Loading class");
                        return;
                }
@@ -3106,15 +3085,15 @@ get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enume
        all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
 
        if (!generic_icollection_class) {
-               generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
+               generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "ICollection`1");
-               generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
+               generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "IEnumerable`1");
-               generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
+               generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "IEnumerator`1");
-               generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
+               generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "IReadOnlyList`1");
-               generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
+               generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "IReadOnlyCollection`1");
        }
 
@@ -3298,7 +3277,7 @@ count_virtual_methods (MonoClass *klass)
 
        if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
                mono_class_setup_methods (klass);
-               if (klass->exception_type)
+               if (mono_class_has_failure (klass))
                        return -1;
 
                for (i = 0; i < klass->method.count; ++i) {
@@ -3766,11 +3745,11 @@ mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
        int i;
        if (!klass->generic_class) {
                mono_class_setup_vtable_full (klass, in_setup);
-               return klass->exception_type == 0;
+               return !mono_class_has_failure (klass);
        }
 
        mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
-       if (klass->generic_class->container_class->exception_type) {
+       if (mono_class_has_failure (klass->generic_class->container_class)) {
                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
                return FALSE;
        }
@@ -3828,7 +3807,7 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
                return;
        }
 
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return;
 
        if (g_list_find (in_setup, klass))
@@ -4222,7 +4201,7 @@ print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, Mono
        g_free (method_signature);
        g_free (type_name);
        mono_class_setup_methods (klass);
-       if (klass->exception_type) {
+       if (mono_class_has_failure (klass)) {
                char *name = mono_type_get_full_name (klass);
                mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
                g_free (name);
@@ -4346,7 +4325,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                mono_class_init (klass->parent);
                mono_class_setup_vtable_full (klass->parent, in_setup);
 
-               if (klass->parent->exception_type) {
+               if (mono_class_has_failure (klass->parent)) {
                        char *name = mono_type_get_full_name (klass->parent);
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
                        g_free (name);
@@ -4385,7 +4364,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                MonoMethod **tmp;
 
                mono_class_setup_vtable_full (gklass, in_setup);
-               if (gklass->exception_type != MONO_EXCEPTION_NONE) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        return;
                }
@@ -4441,7 +4420,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                                
                                mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
                                TRACE_INTERFACE_VTABLE (printf ("    +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
-                               for (j = 0; j < parent_interface->method.count && !klass->exception_type; j++) {
+                               for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
                                        vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
                                        TRACE_INTERFACE_VTABLE (printf ("    --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
                                                        parent_interface_offset + j, parent_interface_offset, j,
@@ -4503,7 +4482,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
                        virt_methods = g_slist_prepend (virt_methods, cm);
                }
-               if (klass->exception_type)
+               if (mono_class_has_failure (klass))
                        goto fail;
        }
        
@@ -4518,7 +4497,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                ic_offset = mono_class_interface_offset (klass, ic);
 
                mono_class_setup_methods (ic);
-               if (ic->exception_type)
+               if (mono_class_has_failure (ic))
                        goto fail;
                
                // Check if this interface is explicitly implemented (instead of just inherited)
@@ -4565,7 +4544,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                                                }
                                        }
                                        TRACE_INTERFACE_VTABLE (printf ("\n"));
-                                       if (klass->exception_type)  /*Might be set by check_interface_method_override*/
+                                       if (mono_class_has_failure (klass))  /*Might be set by check_interface_method_override*/
                                                goto fail;
                                }
                                
@@ -4586,7 +4565,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                                                        }
                                                        break;
                                                }
-                                               if (klass->exception_type) /*Might be set by check_interface_method_override*/
+                                               if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
                                                        goto fail;
                                                TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
                                        }
@@ -4681,7 +4660,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                                                break;
                                        }
                                }
-                               if (k->exception_type)
+                               if (mono_class_has_failure (k))
                                        goto fail;
                                
                                if (slot >= 0) 
@@ -4856,7 +4835,7 @@ mono_method_get_vtable_slot (MonoMethod *method)
 {
        if (method->slot == -1) {
                mono_class_setup_vtable (method->klass);
-               if (method->klass->exception_type)
+               if (mono_class_has_failure (method->klass))
                        return -1;
                if (method->slot == -1) {
                        MonoClass *gklass;
@@ -4952,7 +4931,7 @@ generic_array_methods (MonoClass *klass)
        if (generic_array_method_num)
                return generic_array_method_num;
        mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
-       g_assert (!klass->parent->exception_type); /*So hitting this assert is a huge problem*/
+       g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
        for (i = 0; i < klass->parent->method.count; i++) {
                MonoMethod *m = klass->parent->methods [i];
                if (!strncmp (m->name, "InternalArray__", 15)) {
@@ -5112,18 +5091,18 @@ mono_class_init (MonoClass *klass)
        g_assert (klass);
 
        /* Double-checking locking pattern */
-       if (klass->inited || klass->exception_type)
-               return klass->exception_type == MONO_EXCEPTION_NONE;
+       if (klass->inited || mono_class_has_failure (klass))
+               return !mono_class_has_failure (klass);
 
        /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
 
        /* We do everything inside the lock to prevent races */
        mono_loader_lock ();
 
-       if (klass->inited || klass->exception_type) {
+       if (klass->inited || mono_class_has_failure (klass)) {
                mono_loader_unlock ();
                /* Somebody might have gotten in before us */
-               return klass->exception_type == MONO_EXCEPTION_NONE;
+               return !mono_class_has_failure (klass);
        }
 
        if (klass->init_pending) {
@@ -5143,7 +5122,7 @@ mono_class_init (MonoClass *klass)
                MonoClass *element_class = klass->element_class;
                if (!element_class->inited) 
                        mono_class_init (element_class);
-               if (element_class->exception_type != MONO_EXCEPTION_NONE) {
+               if (mono_class_has_failure (element_class)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        goto leave;
                }
@@ -5161,9 +5140,9 @@ mono_class_init (MonoClass *klass)
 
                mono_class_init (gklass);
                // FIXME: Why is this needed ?
-               if (!gklass->exception_type)
+               if (!mono_class_has_failure (gklass))
                        mono_class_setup_methods (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
                        goto leave;
                }
@@ -5196,7 +5175,7 @@ mono_class_init (MonoClass *klass)
        else
                if (!klass->size_inited){
                        mono_class_setup_fields (klass);
-                       if (klass->exception_type || mono_loader_get_last_error ())
+                       if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
                                goto leave;
                }
                                
@@ -5250,7 +5229,7 @@ mono_class_init (MonoClass *klass)
                klass->has_cctor = gklass->has_cctor;
 
                mono_class_setup_vtable (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        goto leave;
                }
@@ -5282,7 +5261,7 @@ mono_class_init (MonoClass *klass)
                                        klass->has_cctor = 1;
                        } else {
                                mono_class_setup_methods (klass);
-                               if (klass->exception_type)
+                               if (mono_class_has_failure (klass))
                                        goto leave;
 
                                for (i = 0; i < klass->method.count; ++i) {
@@ -5301,7 +5280,7 @@ mono_class_init (MonoClass *klass)
                int first_iface_slot;
                /* This will compute klass->parent->vtable_size for some classes */
                mono_class_init (klass->parent);
-               if (klass->parent->exception_type) {
+               if (mono_class_has_failure (klass->parent)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        goto leave;
                }
@@ -5310,7 +5289,7 @@ mono_class_init (MonoClass *klass)
                if (!klass->parent->vtable_size) {
                        /* FIXME: Get rid of this somehow */
                        mono_class_setup_vtable (klass->parent);
-                       if (klass->parent->exception_type) {
+                       if (mono_class_has_failure (klass->parent)) {
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                goto leave;
                        }
@@ -5329,7 +5308,7 @@ mono_class_init (MonoClass *klass)
                mono_security_core_clr_check_inheritance (klass);
 
        if (mono_loader_get_last_error ()) {
-               if (klass->exception_type == MONO_EXCEPTION_NONE) {
+               if (!mono_class_has_failure (klass)) {
                        set_failure_from_loader_error (klass, mono_loader_get_last_error ());
                }
                mono_loader_clear_error ();
@@ -5348,7 +5327,7 @@ mono_class_init (MonoClass *klass)
 
        mono_loader_unlock ();
 
-       return klass->exception_type == MONO_EXCEPTION_NONE;
+       return !mono_class_has_failure (klass);
 }
 
 /*
@@ -5383,7 +5362,7 @@ mono_class_has_finalizer (MonoClass *klass)
                                 * ignores overrides.
                                 */
                                mono_class_setup_vtable (klass);
-                               if (klass->exception_type || mono_loader_get_last_error ())
+                               if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
                                        cmethod = NULL;
                                else
                                        cmethod = klass->vtable [finalize_slot];
@@ -5738,22 +5717,6 @@ mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char
        mono_error_set_type_load_class (error, klass, msg);
 }
 
-static void
-mono_class_set_failure_from_loader_error (MonoClass *klass, MonoError *error, char *msg)
-{
-       MonoLoaderError *lerror = mono_loader_get_last_error ();
-
-       if (lerror) {
-               set_failure_from_loader_error (klass, lerror);
-               mono_error_set_from_loader_error (error);
-               if (msg)
-                       g_free (msg);
-       } else {
-               mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, msg);
-               mono_error_set_type_load_class (error, klass, msg);
-       }
-}
-
 /**
  * mono_class_create_from_typedef:
  * @image: image where the token is valid
@@ -6221,7 +6184,7 @@ make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
                CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
                pos++;
        } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
-               CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_from_name (mono_defaults.corlib, "System", "ValueType") );
+               CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
        } else {
                CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
        }
@@ -6265,7 +6228,7 @@ make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
 
        if (count - pos > 0) {
                mono_class_setup_vtable (klass->parent);
-               if (klass->parent->exception_type)
+               if (mono_class_has_failure (klass->parent))
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
                else
                        setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
@@ -6747,7 +6710,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
        /* for the building corlib use System.Array from it */
        if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
-               parent = mono_class_from_name (image, "System", "Array");
+               parent = mono_class_load_from_name (image, "System", "Array");
                corlib_type = TRUE;
        } else {
                parent = mono_defaults.array_class;
@@ -6784,7 +6747,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
        if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
                /*Arrays of those two types are invalid.*/
-               mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+               mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
        } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
                if (!eclass->ref_info_handle || eclass->wastypebuilder) {
                        g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
@@ -6801,7 +6764,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                mono_class_init (eclass);
        if (!eclass->size_inited)
                mono_class_setup_fields (eclass);
-       if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
+       if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
 
        klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
@@ -6989,7 +6952,7 @@ static MonoClassField *
 mono_class_get_field_idx (MonoClass *klass, int idx)
 {
        mono_class_setup_fields_locking (klass);
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return NULL;
 
        while (klass) {
@@ -7071,7 +7034,7 @@ mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoTyp
        int i;
 
        mono_class_setup_fields_locking (klass);
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return NULL;
 
        while (klass) {
@@ -7737,7 +7700,8 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
 {
        MonoError error;
        MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
-       g_assert (!mono_error_ok (&error));
+       mono_error_cleanup (&error);
+
        return res;
 }
 
@@ -7840,13 +7804,15 @@ return_nested_in (MonoClass *klass, char *nested)
 }
 
 static MonoClass*
-search_modules (MonoImage *image, const char *name_space, const char *name)
+search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
 {
        MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
        MonoImage *file_image;
        MonoClass *klass;
        int i;
 
+       mono_error_init (error);
+
        /* 
         * The EXPORTEDTYPES table only contains public types, so have to search the
         * modules as well.
@@ -7861,8 +7827,8 @@ search_modules (MonoImage *image, const char *name_space, const char *name)
 
                file_image = mono_image_load_file_for_image (image, i + 1);
                if (file_image) {
-                       klass = mono_class_from_name (file_image, name_space, name);
-                       if (klass)
+                       klass = mono_class_from_name_checked (file_image, name_space, name, error);
+                       if (klass || !is_ok (error))
                                return klass;
                }
        }
@@ -7871,7 +7837,7 @@ search_modules (MonoImage *image, const char *name_space, const char *name)
 }
 
 static MonoClass *
-mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
+mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
 {
        GHashTable *nspace_table;
        MonoImage *loaded_image;
@@ -7904,8 +7870,11 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
        if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
                gboolean res = get_class_from_name (image, name_space, name, &klass);
                if (res) {
-                       if (!klass)
-                               klass = search_modules (image, name_space, name);
+                       if (!klass) {
+                               klass = search_modules (image, name_space, name, error);
+                               if (!is_ok (error))
+                                       return NULL;
+                       }
                        if (nested)
                                return klass ? return_nested_in (klass, nested) : NULL;
                        else
@@ -7928,15 +7897,15 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
                for (i = 0; i < image->module_count; ++i) {
                        MonoImage *module = image->modules [i];
 
-                       klass = mono_class_from_name (module, name_space, name);
-                       if (klass)
+                       klass = mono_class_from_name_checked (module, name_space, name, error);
+                       if (klass || !is_ok (error))
                                return klass;
                }
        }
 
        if (!token) {
-               klass = search_modules (image, name_space, name);
-               if (klass)
+               klass = search_modules (image, name_space, name, error);
+               if (klass || !is_ok (error))
                        return klass;
        }
 
@@ -7957,7 +7926,7 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
                        loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
                        if (!loaded_image)
                                return NULL;
-                       klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
+                       klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
                        if (nested)
                                return klass ? return_nested_in (klass, nested) : NULL;
                        return klass;
@@ -7970,9 +7939,9 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
                        g_assert (image->references [assembly_idx - 1]);
                        if (image->references [assembly_idx - 1] == (gpointer)-1)
                                return NULL;                    
-                       klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
+                       klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
                        if (nested)
-                               return return_nested_in (klass, nested);
+                               return klass ? return_nested_in (klass, nested) : NULL;
                        return klass;
                } else {
                        g_assert_not_reached ();
@@ -7987,6 +7956,18 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
        return klass;
 }
 
+/**
+ * mono_class_from_name_checked:
+ * @image: The MonoImage where the type is looked up in
+ * @name_space: the type namespace
+ * @name: the type short name.
+ *
+ * Obtains a MonoClass with a given namespace and a given name which
+ * is located in the given MonoImage.
+ *
+ * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
+ * set if the class was not found or it will return NULL and set the error if there was a loading error.
+ */
 MonoClass *
 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
 {
@@ -7995,7 +7976,7 @@ mono_class_from_name_checked (MonoImage *image, const char* name_space, const ch
 
        visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
 
-       klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
+       klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
 
        g_hash_table_destroy (visited_images);
 
@@ -8022,13 +8003,61 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
        MonoClass *klass;
 
        klass = mono_class_from_name_checked (image, name_space, name, &error);
-       if (!mono_error_ok (&error)) {
-               mono_loader_set_error_from_mono_error (&error);
-               mono_error_cleanup (&error); /* FIXME Don't swallow the error */
-       }
+       mono_error_cleanup (&error); /* FIXME Don't swallow the error */
+
+       return klass;
+}
+
+/**
+ * mono_class_load_from_name:
+ * @image: The MonoImage where the type is looked up in
+ * @name_space: the type namespace
+ * @name: the type short name.
+ *
+ * This function works exactly like mono_class_from_name but it will abort if the class is not found.
+ * This function should be used by the runtime for critical types to which there's no way to recover but crash
+ * If they are missing. Thing of System.Object or System.String.
+ */
+MonoClass *
+mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
+{
+       MonoError error;
+       MonoClass *klass;
+
+       klass = mono_class_from_name_checked (image, name_space, name, &error);
+       if (!klass)
+               g_error ("Runtime critical type %s.%s not found", name_space, name);
+       if (!mono_error_ok (&error))
+               g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
+       return klass;
+}
+
+/**
+ * mono_class_try_load_from_name:
+ * @image: The MonoImage where the type is looked up in
+ * @name_space: the type namespace
+ * @name: the type short name.
+ *
+ * This function tries to load a type, returning the class was found or NULL otherwise.
+ * This function should be used by the runtime when probing for optional types, those that could have being linked out.
+ *
+ * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
+ * a type that we would otherwise assume to be available but was not due some error.
+ *
+ */
+MonoClass*
+mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
+{
+       MonoError error;
+       MonoClass *klass;
+
+       klass = mono_class_from_name_checked (image, name_space, name, &error);
+       if (!mono_error_ok (&error))
+               g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
        return klass;
 }
 
+
 /**
  * mono_class_is_subclass_of:
  * @klass: class to probe if it is a subclass of another one
@@ -8295,7 +8324,7 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
        if (!oklass->inited)
                mono_class_init (oklass);
 
-       if (klass->exception_type || oklass->exception_type)
+       if (mono_class_has_failure (klass) || mono_class_has_failure  (oklass))
                return FALSE;
 
        if (mono_type_is_generic_argument (&klass->byval_arg)) {
@@ -9127,7 +9156,7 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter)
                return NULL;
        if (!*iter) {
                mono_class_setup_fields_locking (klass);
-               if (klass->exception_type)
+               if (mono_class_has_failure (klass))
                        return NULL;
                /* start from the first */
                if (klass->field.count) {
@@ -9916,7 +9945,7 @@ mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int p
 gboolean
 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
 {
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return FALSE;
 
        mono_loader_lock ();
@@ -9990,7 +10019,7 @@ mono_class_get_exception_for_failure (MonoClass *klass)
 {
        gpointer exception_data = mono_class_get_exception_data (klass);
 
-       switch (klass->exception_type) {
+       switch (mono_class_get_failure(klass)) {
        case MONO_EXCEPTION_TYPE_LOAD: {
                MonoString *name;
                MonoException *ex;
@@ -10029,6 +10058,9 @@ mono_class_get_exception_for_failure (MonoClass *klass)
        case MONO_EXCEPTION_BAD_IMAGE: {
                return mono_get_exception_bad_image_format ((const char *)exception_data);
        }
+       case MONO_EXCEPTION_INVALID_PROGRAM: {
+               return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
+       }
        default: {
                MonoLoaderError *error;
                MonoException *ex;
@@ -10686,14 +10718,12 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error)
                if (!mono_error_ok (error)) {
                        char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
-                       g_free (err_msg);
                }
 
                field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
                if (!mono_error_ok (error)) {
                        char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
-                       g_free (err_msg);
                }
        } else {
                const char *sig;
@@ -10715,8 +10745,8 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error)
                mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
 
                if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
-                       mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);
-                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
                        return;
                }
 
@@ -10725,9 +10755,12 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error)
                mono_metadata_decode_value (sig, &sig);
                /* FIELD signature == 0x06 */
                g_assert (*sig == 0x06);
-               field->type = mono_metadata_parse_type_full (image, container, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
-               if (!field->type)
-                       mono_class_set_failure_from_loader_error (klass, error, g_strdup_printf ("Could not load field %s type", field->name));
+
+               field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
+               if (!field->type) {
+                       char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
+               }
        }
 }
 
@@ -10816,3 +10849,5 @@ mono_class_full_name (MonoClass *klass)
        return mono_type_full_name (&klass->byval_arg);
 }
 
+/* Declare all shared lazy type lookup functions */
+GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)