[metadata] Add a canonical_inst MonoType to MonoClassGtd
authorAleksey Kliger <aleksey@xamarin.com>
Thu, 20 Apr 2017 22:52:40 +0000 (18:52 -0400)
committerAleksey Kliger <aleksey@xamarin.com>
Thu, 20 Apr 2017 22:58:29 +0000 (18:58 -0400)
The canonical instantiation of a generic type definition is the open
instantiation where the GTD is applied to its own generic parameters in order.

Suppose we have `class T<A,B> { ... }` then the canonical instantiation is just "T<A,B>".

mono/metadata/class-accessors.c
mono/metadata/class-internals.h
mono/metadata/class.c
mono/metadata/sre.c

index 327a1c1cfe79bbf76ed0e5f8507a13bf0200c122..ef1bd78da1c006140f6628102bd753954f94cb57 100644 (file)
@@ -382,3 +382,10 @@ mono_class_set_is_com_object (MonoClass *klass)
        mono_loader_unlock ();
 #endif
 }
+
+MonoType*
+mono_class_gtd_get_canonical_inst (MonoClass *klass)
+{
+       g_assert (mono_class_is_gtd (klass));
+       return &((MonoClassGtd*)klass)->canonical_inst;
+}
index 7d85d8ce84f9010140021b975b495d572b119b81..39061bd142a1ec1e5411aaee98f7848babe99d1b 100644 (file)
@@ -390,6 +390,9 @@ typedef struct {
 typedef struct {
        MonoClassDef class;
        MonoGenericContainer *generic_container;
+       /* The canonical GENERICINST where we instantiate a generic type definition with its own generic parameters.*/
+       /* Suppose we have class T`2<A,B> {...}.  canonical_inst is the GTD T`2 applied to A and B. */
+       MonoType canonical_inst;
 } MonoClassGtd;
 
 typedef struct {
@@ -1444,6 +1447,9 @@ mono_class_try_get_generic_container (MonoClass *klass);
 void
 mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container);
 
+MonoType*
+mono_class_gtd_get_canonical_inst (MonoClass *klass);
+
 guint32
 mono_class_get_first_method_idx (MonoClass *klass);
 
index cd15ef8ea77dda8f112f841eab872d4b241e10f5..ac7ea15d7b0e53ac90bb2f8544196d868ec12757 100644 (file)
@@ -5574,6 +5574,9 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
                generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
                context = &generic_container->context;
                mono_class_set_generic_container (klass, generic_container);
+               MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
+               canonical_inst->type = MONO_TYPE_GENERICINST;
+               canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
                enable_gclass_recording ();
        }
 
index 2d833eacdcbb8b9aaa78b597b11579e793458423..2b6f6e8ecf0d9c56cd56de318a8bb11cc98f3ee0 100644 (file)
@@ -2537,6 +2537,11 @@ reflection_create_generic_class (MonoReflectionTypeBuilderHandle ref_tb, MonoErr
        }
 
        generic_container->context.class_inst = mono_get_shared_generic_inst (generic_container);
+       MonoGenericContext* context = &generic_container->context;
+       MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
+       canonical_inst->type = MONO_TYPE_GENERICINST;
+       canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
+
 leave:
        HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
 }