2004-02-09 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / class.c
index 725053af978fa3a22365ef326f6d3f90173163dd..6b8d75728face562a7abdf015799acb7d0a052bf 100644 (file)
@@ -199,29 +199,32 @@ mono_class_is_open_constructed_type (MonoType *t)
 }
 
 MonoType*
-mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst)
+mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst,
+                                MonoGenericMethod *gmethod)
 {
        switch (type->type) {
        case MONO_TYPE_MVAR:
-               if (ginst)
-                       return dup_type (ginst->type_argv [type->data.generic_param->num]);
+               if (gmethod && gmethod->mtype_argv)
+                       return dup_type (gmethod->mtype_argv [type->data.generic_param->num]);
                else
                        return type;
-       case MONO_TYPE_VAR: {
-               MonoType *t = ginst->type_argv [type->data.generic_param->num];
-
-               if ((t->type == MONO_TYPE_VAR) || (t->type == MONO_TYPE_MVAR))
+       case MONO_TYPE_VAR:
+               if (ginst) {
+                       MonoType *t = ginst->type_argv [type->data.generic_param->num];
+
+                       if ((t->type == MONO_TYPE_VAR) || (t->type == MONO_TYPE_MVAR))
+                               return type;
+                       else
+                               return dup_type (t);
+               } else
                        return type;
-               else
-                       return dup_type (t);
-       }
        case MONO_TYPE_SZARRAY: {
                MonoClass *eclass = type->data.klass;
                MonoClass *nclass;
                MonoType *nt;
-               if (eclass->byval_arg.type == MONO_TYPE_MVAR) {
-                       nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]);
-               } else if (eclass->byval_arg.type == MONO_TYPE_VAR) {
+               if ((eclass->byval_arg.type == MONO_TYPE_MVAR) && gmethod) {
+                       nclass = mono_class_from_mono_type (gmethod->mtype_argv [eclass->byval_arg.data.generic_param->num]);
+               } else if ((eclass->byval_arg.type == MONO_TYPE_VAR) && ginst) {
                        nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]);
                } else {
                        return type;
@@ -243,7 +246,7 @@ mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst)
 
                for (i = 0; i < oginst->type_argc; i++) {
                        MonoType *t = oginst->type_argv [i];
-                       nginst->type_argv [i] = mono_class_inflate_generic_type (t, ginst);
+                       nginst->type_argv [i] = mono_class_inflate_generic_type (t, ginst, gmethod);
                };
 
                nt = dup_type (type);
@@ -256,16 +259,18 @@ mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst)
        return type;
 }
 
-MonoMethodSignature*
-mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericInst *ginst)
+static MonoMethodSignature*
+inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig,
+                          MonoGenericMethod *gmethod)
 {
        MonoMethodSignature *res;
        int i;
        res = mono_metadata_signature_alloc (image, sig->param_count);
-       res->ret = mono_class_inflate_generic_type (sig->ret, ginst);
-       for (i = 0; i < sig->param_count; ++i) {
-               res->params [i] = mono_class_inflate_generic_type (sig->params [i], ginst);
-       }
+       res->ret = mono_class_inflate_generic_type (sig->ret, gmethod->generic_inst, gmethod);
+       for (i = 0; i < sig->param_count; ++i)
+               res->params [i] = mono_class_inflate_generic_type (sig->params [i],
+                                                                  gmethod->generic_inst,
+                                                                  gmethod);
        res->hasthis = sig->hasthis;
        res->explicit_this = sig->explicit_this;
        res->call_convention = sig->call_convention;
@@ -274,7 +279,7 @@ mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig
 }
 
 static MonoMethodHeader*
-inflate_generic_header (MonoMethodHeader *header, MonoGenericInst *ginst)
+inflate_generic_header (MonoMethodHeader *header, MonoGenericMethod *gmethod)
 {
        MonoMethodHeader *res;
        int i;
@@ -287,15 +292,16 @@ inflate_generic_header (MonoMethodHeader *header, MonoGenericInst *ginst)
        res->num_locals = header->num_locals;
        res->clauses = header->clauses;
        res->gen_params = header->gen_params;
-       res->geninst = ginst;
-       for (i = 0; i < header->num_locals; ++i) {
-               res->locals [i] = mono_class_inflate_generic_type (header->locals [i], ginst);
-       }
+       res->gen_method = gmethod;
+       for (i = 0; i < header->num_locals; ++i)
+               res->locals [i] = mono_class_inflate_generic_type (header->locals [i],
+                                                                  gmethod->generic_inst,
+                                                                  gmethod);
        return res;
 }
 
 MonoMethod*
-mono_class_inflate_generic_method (MonoMethod *method, MonoGenericInst *ginst)
+mono_class_inflate_generic_method (MonoMethod *method, MonoGenericMethod *gmethod)
 {
        MonoMethod *result;
        if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
@@ -307,11 +313,11 @@ mono_class_inflate_generic_method (MonoMethod *method, MonoGenericInst *ginst)
                *nmethod = *(MonoMethodNormal*)method;
                result = (MonoMethod*)nmethod;
                if (nmethod->header)
-                       nmethod->header = inflate_generic_header (nmethod->header, ginst);
+                       nmethod->header = inflate_generic_header (nmethod->header, gmethod);
        }
-       if (ginst->klass)
-               result->klass = ginst->klass;
-       result->signature = mono_class_inflate_generic_signature (method->klass->image, result->signature, ginst);
+       result->klass = gmethod->klass;
+       result->signature = inflate_generic_signature (
+               method->klass->image, result->signature, gmethod);
        return result;
 }
 
@@ -392,7 +398,7 @@ class_compute_field_layout (MonoClass *class)
                if (mono_field_is_deleted (field))
                        continue;
                if (class->generic_inst) {
-                       field->type = mono_class_inflate_generic_type (field->type, class->generic_inst->data.generic_inst);
+                       field->type = mono_class_inflate_generic_type (field->type, class->generic_inst, NULL);
                        field->type->attrs = cols [MONO_FIELD_FLAGS];
                }
 
@@ -1670,7 +1676,7 @@ get_instantiation_name (const char *name, MonoGenericInst *ginst)
 static void
 mono_class_initialize_generic (MonoGenericInst *ginst, gboolean inflate_methods)
 {
-       MonoClass *klass, *gklass;
+       MonoClass *klass, *gklass, *pklass;
 
        if (ginst->initialized || ginst->init_pending)
                return;
@@ -1681,7 +1687,12 @@ mono_class_initialize_generic (MonoGenericInst *ginst, gboolean inflate_methods)
        klass = ginst->klass;
        klass->name = get_instantiation_name (gklass->name, ginst);
 
-       mono_class_setup_parent (klass, gklass->parent);
+       if (ginst->parent)
+               pklass = mono_class_from_mono_type (ginst->parent);
+       else
+               pklass = gklass->parent;
+
+       mono_class_setup_parent (klass, pklass);
        mono_class_setup_mono_type (klass);
 
        if (inflate_methods) {
@@ -1690,20 +1701,26 @@ mono_class_initialize_generic (MonoGenericInst *ginst, gboolean inflate_methods)
                klass->field = gklass->field;
                klass->method = gklass->method;
                klass->methods = g_new0 (MonoMethod *, klass->method.count);
-               for (i = 0; i < klass->method.count; i++)
-                       klass->methods [i] = mono_class_inflate_generic_method (gklass->methods [i], ginst);
+
+               for (i = 0; i < klass->method.count; i++) {
+                       MonoGenericMethod *gmethod = g_new0 (MonoGenericMethod, 1);
+
+                       gmethod->klass = klass;
+                       gmethod->generic_method = gklass->methods [i];
+                       gmethod->generic_inst = ginst;
+
+                       klass->methods [i] = mono_class_inflate_generic_method (
+                               gklass->methods [i], gmethod);
+               }
        }
 
-       g_hash_table_insert (klass->image->generics_cache, ginst->generic_type, klass);
        ginst->initialized = TRUE;
 }
 
 MonoClass*
-mono_class_from_generic (MonoType *gtype, gboolean inflate_methods)
+mono_class_from_generic (MonoGenericInst *ginst)
 {
-       MonoGenericInst *ginst = gtype->data.generic_inst;
-       MonoClass *class, *gklass;
-       MonoImage *image;
+       MonoClass *class, *gklass, *pklass;
 
        if (ginst->klass) {
                mono_class_initialize_generic (ginst, TRUE);
@@ -1715,37 +1732,16 @@ mono_class_from_generic (MonoType *gtype, gboolean inflate_methods)
        gklass = mono_class_from_mono_type (ginst->generic_type);
        mono_class_init (gklass);
 
-       image = gklass->image;
-       if ((class = g_hash_table_lookup (image->generics_cache, gtype))) {
-               mono_loader_unlock ();
-               return class;
-       }
-
-       class = g_malloc0 (sizeof (MonoClass));
+       class = ginst->klass = g_malloc0 (sizeof (MonoClass));
        class->name_space = gklass->name_space;
        class->name = get_instantiation_name (gklass->name, ginst);
-       class->image = image;
+       class->image = gklass->image;
        class->flags = gklass->flags;
 
-       class->generic_inst = gtype;
+       class->generic_inst = ginst;
 
        class->cast_class = class->element_class = class;
 
-       if (inflate_methods) {
-               int i;
-
-               mono_class_setup_parent (class, gklass->parent);
-               mono_class_setup_mono_type (class);
-
-               class->field = gklass->field;
-               class->method = gklass->method;
-               class->methods = g_new0 (MonoMethod *, class->method.count);
-               for (i = 0; i < class->method.count; i++)
-                       class->methods [i] = mono_class_inflate_generic_method (gklass->methods [i], ginst);
-       }
-
-       g_hash_table_insert (image->generics_cache, gtype, class);
-
        mono_loader_unlock ();
 
        return class;
@@ -1773,8 +1769,6 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
                klass->parent = mono_defaults.object_class;
 
        if (count - pos > 0) {
-               int j;
-
                klass->interface_count = count - pos;
                klass->interfaces = g_new0 (MonoClass *, count - pos);
                for (i = pos; i < count; i++)
@@ -1786,7 +1780,7 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb
        klass->image = image;
        klass->cast_class = klass->element_class = klass;
        klass->enum_basetype = &klass->element_class->byval_arg;
-       klass->flags = TYPE_ATTRIBUTE_INTERFACE;
+       klass->flags = TYPE_ATTRIBUTE_INTERFACE | TYPE_ATTRIBUTE_PUBLIC;
 
        klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
        klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
@@ -1812,7 +1806,7 @@ my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
        klass->image = mono_defaults.corlib;
        klass->cast_class = klass->element_class = klass;
        klass->enum_basetype = &klass->element_class->byval_arg;
-       klass->flags = TYPE_ATTRIBUTE_INTERFACE;
+       klass->flags = TYPE_ATTRIBUTE_INTERFACE | TYPE_ATTRIBUTE_PUBLIC;
 
        klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
        klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
@@ -1958,7 +1952,7 @@ mono_class_from_mono_type (MonoType *type)
        case MONO_TYPE_VALUETYPE:
                return type->data.klass;
        case MONO_TYPE_GENERICINST:
-               return mono_class_from_generic (type, TRUE);
+               return mono_class_from_generic (type->data.generic_inst);
        case MONO_TYPE_VAR:
                return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
        case MONO_TYPE_MVAR:
@@ -1994,7 +1988,7 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
                class = mono_class_from_mono_type (type->data.type);
                break;
        case MONO_TYPE_GENERICINST:
-               class = mono_class_from_generic (type, TRUE);
+               class = mono_class_from_generic (type->data.generic_inst);
                break;
        default:
                /* it seems any type can be stored in TypeSpec as well */