Merge branch 'master' into msbuilddll2
[mono.git] / mono / metadata / class.c
index eb71ed4a3e3d92614760d83e6d9b1eb81ed7c69b..b64c1086e039b0594608e7f2d1c64f9dbd82e47b 100644 (file)
@@ -42,6 +42,8 @@
 #include <mono/utils/mono-logger-internal.h>
 #include <mono/utils/mono-memory-model.h>
 #include <mono/utils/atomic.h>
+#include <mono/utils/bsearch.h>
+
 MonoStats mono_stats;
 
 gboolean mono_print_vtable = FALSE;
@@ -53,7 +55,7 @@ guint32 classes_size, class_ext_size;
 /* Function supplied by the runtime to find classes by name using information from the AOT file */
 static MonoGetClassFromName get_class_from_name = NULL;
 
-static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
+static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
@@ -69,7 +71,6 @@ 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;
 
 
 /*
@@ -217,8 +218,15 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
                                guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
                                const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
 
-                               if (strcmp (nname, name) == 0)
-                                       return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
+                               if (strcmp (nname, name) == 0) {
+                                       MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
+                                       if (!mono_error_ok (&error)) {
+                                               mono_loader_set_error_from_mono_error (&error);
+                                               mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
+                                               return NULL;
+                                       }
+                                       return res;
+                               }
 
                                i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
                        }
@@ -1419,6 +1427,52 @@ mono_class_setup_fields (MonoClass *class)
        MonoGenericContainer *container = NULL;
        MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
 
+       /*
+        * FIXME: We have a race condition here.  It's possible that this function returns
+        * to its caller with `instance_size` set to `0` instead of the actual size.  This
+        * is not a problem when the function is called recursively on the same class,
+        * because the size will be initialized by the outer invocation.  What follows is a
+        * description of how it can occur in other cases, too.  There it is a problem,
+        * because it can lead to the GC being asked to allocate an object of size `0`,
+        * which SGen chokes on.  The race condition is triggered infrequently by
+        * `tests/sgen-suspend.cs`.
+        *
+        * This function is called for a class whenever one of its subclasses is inited.
+        * For example, it's called for every subclass of Object.  What it does is this:
+        *
+        *     if (class->setup_fields_called)
+        *         return;
+        *     ...
+        *     class->instance_size = 0;
+        *     ...
+        *     class->setup_fields_called = 1;
+        *     ... critical point
+        *     class->instance_size = actual_instance_size;
+        *
+        * The last two steps are sometimes reversed, but that only changes the way in which
+        * the race condition works.
+        *
+        * Assume thread A goes through this function and makes it to the critical point.
+        * Now thread B runs the function and, since `setup_fields_called` is set, returns
+        * immediately, but `instance_size` is incorrect.
+        *
+        * The other case looks like this:
+        *
+        *     if (class->setup_fields_called)
+        *         return;
+        *     ... critical point X
+        *     class->instance_size = 0;
+        *     ... critical point Y
+        *     class->instance_size = actual_instance_size;
+        *     ...
+        *     class->setup_fields_called = 1;
+        *
+        * Assume thread A goes through the function and makes it to critical point X.  Now
+        * thread B runs through the whole of the function, returning, assuming
+        * `instance_size` is set.  At that point thread A gets to run and makes it to
+        * critical point Y, at which time `instance_size` is `0` again, invalidating thread
+        * B's assumption.
+        */
        if (class->setup_fields_called)
                return;
 
@@ -1496,6 +1550,7 @@ mono_class_setup_fields (MonoClass *class)
                mono_memory_barrier ();
                class->size_inited = 1;
                class->fields_inited = 1;
+               class->setup_fields_called = 1;
                return;
        }
 
@@ -2113,9 +2168,6 @@ mono_class_setup_methods (MonoClass *class)
 
        class->methods = methods;
 
-       if (mono_debugger_class_loaded_methods_func)
-               mono_debugger_class_loaded_methods_func (class);
-
        mono_loader_unlock ();
 }
 
@@ -2638,7 +2690,7 @@ compare_interface_ids (const void *p_key, const void *p_element) {
 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
 int
 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
-       MonoClass **result = bsearch (
+       MonoClass **result = mono_binary_search (
                        itf,
                        klass->interfaces_packed,
                        klass->interface_offsets_count,
@@ -2867,9 +2919,12 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
         * 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.
+        *
+        * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
+        * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
         */
-       nifaces = generic_ireadonlylist_class ? 5 : 3;
        if (eclass->valuetype) {
+               nifaces = generic_ireadonlylist_class ? 5 : 3;
                fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
 
                /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
@@ -2891,6 +2946,7 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
                int idepth = eclass->idepth;
                if (!internal_enumerator)
                        idepth--;
+               nifaces = generic_ireadonlylist_class ? 2 : 3;
 
                // FIXME: This doesn't seem to work/required for generic params
                if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
@@ -2954,10 +3010,16 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
 
                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 (eclass->valuetype) {
+                       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);
+                       }
+               } else {
+                       if (!generic_ireadonlylist_class)
+                               interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
                }
        }
        if (internal_enumerator) {
@@ -3551,10 +3613,6 @@ mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
        if (class->vtable)
                return;
 
-       if (mono_debug_using_mono_debugger ())
-               /* The debugger currently depends on this */
-               mono_class_setup_methods (class);
-
        if (MONO_CLASS_IS_INTERFACE (class)) {
                /* This sets method->slot for all methods if this is an interface */
                mono_class_setup_methods (class);
@@ -5304,7 +5362,7 @@ mono_class_setup_mono_type (MonoClass *class)
 
 #ifndef DISABLE_COM
 /*
- * COM initialization (using mono_init_com_types) is delayed until needed. 
+ * COM initialization is delayed until needed.
  * However when a [ComImport] attribute is present on a type it will trigger
  * the initialization. This is not a problem unless the BCL being executed 
  * lacks the types that COM depends on (e.g. Variant on Silverlight).
@@ -5325,7 +5383,6 @@ 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*/
 
@@ -5358,7 +5415,7 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                if (MONO_CLASS_IS_IMPORT (class)) {
                        init_com_from_comimport (class);
                        if (parent == mono_defaults.object_class)
-                               parent = mono_defaults.com_object_class;
+                               parent = mono_class_get_com_object_class ();
                }
 #endif
                if (!parent) {
@@ -5429,7 +5486,7 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
  *  - supertypes: array of classes: each element has a class in the hierarchy
  *    starting from @class up to System.Object
  * 
- * LOCKING: this assumes the loader lock is held
+ * LOCKING: This function is atomic, in case of contention we waste memory.
  */
 void
 mono_class_setup_supertypes (MonoClass *class)
@@ -5437,7 +5494,8 @@ mono_class_setup_supertypes (MonoClass *class)
        int ms;
        MonoClass **supertypes;
 
-       if (class->supertypes)
+       mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
+       if (supertypes)
                return;
 
        if (class->parent && !class->parent->supertypes)
@@ -5475,10 +5533,34 @@ fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
        return TRUE;
 }
 
+static void
+mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
+{
+       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
+       mono_error_set_type_load_class (error, class, msg);
+}
+
+static void
+mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
+{
+       MonoLoaderError *lerror = mono_loader_get_last_error ();
+
+       if (lerror) {
+               set_failure_from_loader_error (class, lerror);
+               mono_error_set_from_loader_error (error);
+               if (msg)
+                       g_free (msg);
+       } else {
+               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
+               mono_error_set_type_load_class (error, class, msg);
+       }
+}
+
 /**
  * mono_class_create_from_typedef:
  * @image: image where the token is valid
  * @type_token:  typedef token
+ * @error:  used to return any error found while creating the type
  *
  * Create the MonoClass* representing the specified type token.
  * @type_token must be a TypeDef token.
@@ -5486,7 +5568,7 @@ fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
  * FIXME: don't return NULL on failure, just the the caller figure it out.
  */
 static MonoClass *
-mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
+mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
 {
        MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
        MonoClass *class, *parent = NULL;
@@ -5500,13 +5582,19 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        guint32 field_last, method_last;
        guint32 nesting_tokeen;
 
-       if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows)
+       mono_error_init (error);
+
+       if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
+               mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
+               g_assert (!mono_loader_get_last_error ());
                return NULL;
+       }
 
        mono_loader_lock ();
 
        if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
                mono_loader_unlock ();
+               g_assert (!mono_loader_get_last_error ());
                return class;
        }
 
@@ -5557,19 +5645,18 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                }
                parent = mono_class_get_full (image, parent_token, context);
 
-               if (parent == NULL){
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load parent type"));
-                       mono_loader_clear_error ();
+               if (parent == NULL) {
+                       mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
                        goto parent_failure;
                }
 
                for (tmp = parent; tmp; tmp = tmp->parent) {
                        if (tmp == class) {
-                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cycle found while resolving parent"));
+                               mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
                                goto parent_failure;
                        }
                        if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
-                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Parent extends generic instance of this type"));
+                               mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
                                goto parent_failure;
                        }
                }
@@ -5588,11 +5675,13 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
         * so it has to come after setup_mono_type ().
         */
        if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
-               class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen);
-               if (!class->nested_in) {
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load nestedin type"));
+               class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
+               if (!mono_error_ok (error)) {
+                       /*FIXME implement a mono_class_set_failure_from_mono_error */
+                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
                        mono_loader_unlock ();
                        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+                       g_assert (!mono_loader_get_last_error ());
                        return NULL;
                }
        }
@@ -5610,7 +5699,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        if (!class->enumtype) {
                if (!mono_metadata_interfaces_from_typedef_full (
                            image, type_token, &interfaces, &icount, FALSE, context)){
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load interfaces"));
+                       mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
                        mono_loader_unlock ();
                        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
                        return NULL;
@@ -5660,9 +5749,10 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                if (!enum_basetype) {
                        /*set it to a default value as the whole runtime can't handle this to be null*/
                        class->cast_class = class->element_class = mono_defaults.int32_class;
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       mono_class_set_failure_and_error (class, error, "Could not enum basetype");
                        mono_loader_unlock ();
                        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+                       g_assert (!mono_loader_get_last_error ());
                        return NULL;
                }
                class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
@@ -5674,12 +5764,10 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
         * work.
         */
        if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
-               char *class_name = g_strdup_printf("%s.%s", class->name_space, class->name);
-               char *error = concat_two_strings_with_zero (class->image, class_name, class->image->assembly_name);
-               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, error);
-               g_free (class_name);
+               mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
                mono_loader_unlock ();
                mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+               g_assert (!mono_loader_get_last_error ());
                return NULL;
        }
 
@@ -5691,6 +5779,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        mono_loader_unlock ();
 
        mono_profiler_class_loaded (class, MONO_PROFILE_OK);
+       g_assert (!mono_loader_get_last_error ());
 
        return class;
 
@@ -5698,8 +5787,8 @@ parent_failure:
        mono_class_setup_mono_type (class);
        mono_loader_unlock ();
        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+       g_assert (!mono_loader_get_last_error ());
        return NULL;
-
 }
 
 /** is klass Nullable<T>? */
@@ -6551,6 +6640,9 @@ mono_class_data_size (MonoClass *klass)
 {      
        if (!klass->inited)
                mono_class_init (klass);
+       /* This can happen with dynamically created types */
+       if (!klass->fields_inited)
+               mono_class_setup_fields_locking (klass);
 
        /* in arrays, sizes.class_size is unioned with element_size
         * and arrays have no static fields
@@ -7003,7 +7095,13 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c
 
        switch (type_token & 0xff000000){
        case MONO_TOKEN_TYPE_DEF:
-               class = mono_class_create_from_typedef (image, type_token);
+               class = mono_class_create_from_typedef (image, type_token, &error);
+               if (!mono_error_ok (&error)) {
+                       mono_loader_set_error_from_mono_error (&error);
+                       /*FIXME don't swallow the error message*/
+                       mono_error_cleanup (&error);
+                       return NULL;
+               }
                break;          
        case MONO_TOKEN_TYPE_REF:
                class = mono_class_from_typeref (image, type_token);
@@ -7354,7 +7452,11 @@ search_modules (MonoImage *image, const char *name_space, const char *name)
  * @name: the type short name.
  *
  * Obtains a MonoClass with a given namespace and a given name which
- * is located in the given MonoImage.   
+ * is located in the given MonoImage.
+ *
+ * To reference nested classes, use the "/" character as a separator.
+ * For example use "Foo/Bar" to reference the class Bar that is nested
+ * inside Foo, like this: "class Foo { class Bar {} }".
  */
 MonoClass *
 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
@@ -7466,11 +7568,31 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
        return class;
 }
 
-/*FIXME test for interfaces with variant generic arguments*/
+/**
+ * mono_class_is_subclass_of:
+ * @klass: class to probe if it is a subclass of another one
+ * @klassc: the class we suspect is the base class
+ * @check_interfaces: whether we should perform interface checks
+ *
+ * This method determines whether @klass is a subclass of @klassc.
+ *
+ * If the @check_interfaces flag is set, then if @klassc is an interface
+ * this method return true if the @klass implements the interface or
+ * if @klass is an interface, if one of its base classes is @klass.
+ *
+ * If @check_interfaces is false then, then if @klass is not an interface
+ * then it returns true if the @klass is a subclass of @klassc.
+ *
+ * if @klass is an interface and @klassc is System.Object, then this function
+ * return true.
+ *
+ */
 gboolean
 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
                           gboolean check_interfaces)
 {
+/*FIXME test for interfaces with variant generic arguments*/
+       
        if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
                if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
                        return TRUE;
@@ -8538,7 +8660,7 @@ mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
        MonoMethod** method;
        if (!iter)
                return NULL;
-       if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
+       if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
                if (!*iter) {
                        mono_class_setup_methods (klass);
                        /*
@@ -8731,6 +8853,7 @@ mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
 MonoClass*
 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
 {
+       MonoError error;
        GList *item;
        int i;
 
@@ -8746,9 +8869,11 @@ mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
                                MonoClass* nclass;
                                guint32 cols [MONO_NESTED_CLASS_SIZE];
                                mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
-                               nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
-                               if (!nclass) {
-                                       mono_loader_clear_error ();
+                               nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
+                               if (!mono_error_ok (&error)) {
+                                       /*FIXME don't swallow the error message*/
+                                       mono_error_cleanup (&error);
+
                                        i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
                                        continue;
                                }
@@ -8782,6 +8907,32 @@ mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
        return NULL;
 }
 
+
+/**
+ * mono_class_is_delegate
+ * @klass: the MonoClass to act on
+ *
+ * Returns: true if the MonoClass represents a System.Delegate.
+ */
+mono_bool
+mono_class_is_delegate (MonoClass *klass)
+{
+       return klass->delegate;
+}
+
+/**
+ * mono_class_implements_interface
+ * @klass: The MonoClass to act on
+ * @interface: The interface to check if @klass implements.
+ *
+ * Returns: true if @klass implements @interface.
+ */
+mono_bool
+mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
+{
+       return mono_class_is_assignable_from (iface, klass);
+}
+
 /**
  * mono_field_get_name:
  * @field: the MonoClassField to act on
@@ -9721,6 +9872,21 @@ mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, Mo
        return TRUE;
 }
 
+/*
+ * mono_class_can_access_class:
+ * @source_class: The source class 
+ * @target_class: The accessed class
+ * 
+ * This function returns is @target_class is visible to @source_class
+ * 
+ * Returns: TRUE if source have proper visibility and acessibility to target
+ */
+gboolean
+mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
+{
+       return can_access_type (source_class, target_class);
+}
+
 /**
  * mono_type_is_valid_enum_basetype:
  * @type: The MonoType to check
@@ -9943,16 +10109,8 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error)
                /* FIELD signature == 0x06 */
                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);
-                       if (lerror)
-                               set_failure_from_loader_error (class, lerror);
-                       else
-                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
-                       mono_loader_clear_error ();
-               }
+               if (!field->type)
+                       mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
        }
 }