From ac1d494270ac25b3fd885ef7d8b52cb27109861d Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Thu, 28 Sep 2017 13:45:54 -0700 Subject: [PATCH] [runtime] Synthesize IList and IReadOnlyList for the element type of enum errays. Fixes #59824 Make sure array of enums can be casted to interfaces of their element types. --- mono/metadata/class.c | 24 +++++++++++---- mono/tests/array.cs | 70 +++++++++++++++++++++++++------------------ 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/mono/metadata/class.c b/mono/metadata/class.c index e1539de106c..da8fc30585b 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -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; diff --git a/mono/tests/array.cs b/mono/tests/array.cs index b0e9d47ff1e..7b3a68247a8 100644 --- a/mono/tests/array.cs +++ b/mono/tests/array.cs @@ -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 )(object)x; + } catch (Exception e) { return 1; - puts ("e"); - if (jagged () != 0) - return 1; - - + } + try { + var y = (IList)(object)x; + } catch (Exception e) { + return 2; + } + + try { + var y = (ICollection)(object)x; + } catch (Exception e) { + return 3; + } + + try { + var y = (IEnumerable)(object)x; + } catch (Exception e) { + return 4; + } + + try { + var y = (IReadOnlyCollection)(object)x; + } catch (Exception e) { + return 5; + } return 0; } + + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Test), args); + } } -- 2.25.1