[runtime] Synthesize IList and IReadOnlyList for the element type of enum errays...
authorRodrigo Kumpera <kumpera@gmail.com>
Thu, 28 Sep 2017 20:45:54 +0000 (13:45 -0700)
committerRodrigo Kumpera <kumpera@gmail.com>
Thu, 28 Sep 2017 20:45:54 +0000 (13:45 -0700)
Make sure array of enums can be casted to interfaces of their element types.

mono/metadata/class.c
mono/tests/array.cs

index e1539de106cd4bb92eaa32c27f30e5795facc6cd..da8fc30585b67fb1fa23f44a182cb0ae2ea3ce3f 100644 (file)
@@ -4955,12 +4955,19 @@ mono_class_init (MonoClass *klass)
                ghcimpl = cached_info.ghcimpl;
                has_cctor = cached_info.has_cctor;
        } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
-               /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
+               /* SZARRAY can have 3 vtable layouts, with and without the stelemref method and enum element type
                 * The first slot if for array with.
                 */
-               static int szarray_vtable_size[2] = { 0 };
+               static int szarray_vtable_size[3] = { 0 };
 
-               int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
+               int slot;
+
+               if (MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg))
+                       slot = 0;
+               else if (klass->element_class->enumtype)
+                       slot = 1;
+               else
+                       slot = 2;
 
                /* SZARRAY case */
                if (!szarray_vtable_size [slot]) {
@@ -10540,8 +10547,8 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
        if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
                MonoType *args [1];
 
-               /* generic IList, ICollection, IEnumerable */
-               interface_count = 2;
+               /* IList and IReadOnlyList -> 2x if enum*/
+               interface_count = klass->element_class->enumtype ? 4 : 2;
                interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
 
                args [0] = &klass->element_class->byval_arg;
@@ -10549,6 +10556,13 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
                        mono_defaults.generic_ilist_class, 1, args, FALSE);
                interfaces [1] = mono_class_bind_generic_parameters (
                           mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
+               if (klass->element_class->enumtype) {
+                       args [0] = mono_class_enum_basetype (klass->element_class);
+                       interfaces [2] = mono_class_bind_generic_parameters (
+                               mono_defaults.generic_ilist_class, 1, args, FALSE);
+                       interfaces [3] = mono_class_bind_generic_parameters (
+                                  mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
+               }
        } else if (mono_class_is_ginst (klass)) {
                MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
 
index b0e9d47ff1e778425504e95dfd9e0c8307341fd6..7b3a68247a8f16df2176a2622b2b58b6a91615af 100644 (file)
@@ -1,14 +1,10 @@
 using System;
+using System.Collections.Generic;
 using System.Runtime.InteropServices;
 
 public class Test {
 
-       static void puts (string s)
-       {
-               Console.WriteLine (s);
-       }
-
-       public static int jagged ()
+       public static int test_0_jagged ()
        {
                int[][] j2 = new int [3][];
 
@@ -32,7 +28,7 @@ public class Test {
                return 0;
        }
 
-       public static int stest ()
+       public static int test_0_stest ()
        {
                string[] sa = new string[32];
 
@@ -44,13 +40,13 @@ public class Test {
 
                for (int i = 0; i < sa.Length; i++){
                        if (sa [i] != null)
-                               puts (sa [i]);
+                               Console.WriteLine (sa [i]);
                }
                
                return 0;
        }
        
-       public static int atest2 ()
+       public static int test_0_atest2 ()
        {
                int[,] ia = new int[32,32];
 
@@ -71,7 +67,7 @@ public class Test {
                return 0;
        }
        
-       public static int atest ()
+       public static int test_0_atest ()
        {
                int[] ia = new int[32];
 
@@ -93,35 +89,51 @@ public class Test {
 
                for (int i = 0; i <ia.Length; i++)
                        if ((int)ia.GetValue (i) != i*i*i){
-                               puts ("Crap: " + i + " " + (int) ia.GetValue (i) );
+                               Console.WriteLine ("Crap: " + i + " " + (int) ia.GetValue (i) );
 
                                return 4;
                        }
                
                return 0;
        }
-       
 
-       public static int Main () {
-               puts ("a");
-               if (atest () != 0)
-                       return atest ();
-               puts ("b");     
-               if (atest2 () != 0)
-                       return 1;
-               puts ("c");
-               if (atest2 () != 0)
-                       return 1;
-               puts ("d");     
-               if (stest () != 0)
+       enum Foo { a, b };
+       public static int test_0_enum_array_casting () {
+        var x = new Foo[10];
+               try {
+                       var y = (IReadOnlyList<int>)(object)x;
+               } catch (Exception e) {
                        return 1;
-               puts ("e");     
-               if (jagged () != 0)
-                       return 1;
-               
-               
+               }
+               try {
+                       var y = (IList<int>)(object)x;
+               } catch (Exception e) {
+                       return 2;
+               }
+
+               try {
+                       var y = (ICollection<int>)(object)x;
+               } catch (Exception e) {
+                       return 3;
+               }
+
+               try {
+                       var y = (IEnumerable<int>)(object)x;
+               } catch (Exception e) {
+                       return 4;
+               }
+
+               try {
+                       var y = (IReadOnlyCollection<int>)(object)x;
+               } catch (Exception e) {
+                       return 5;
+               }
                return 0;
        }
+
+       public static int Main (string[] args) {
+               return TestDriver.RunTests (typeof (Test), args);
+       }
 }