File mono-12802.diff of Package mono

diff --git a/mono/metadata/class-init.c b/mono/metadata/class-init.c
index 670446618186..802bd8d96855 100644
--- a/mono/metadata/class-init.c
+++ b/mono/metadata/class-init.c
@@ -1410,13 +1410,15 @@ print_implemented_interfaces (MonoClass *klass)
 	printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
 	g_free (name);
 
-	for (i = 0; i < klass->interface_offsets_count; i++)
-		printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
+	for (i = 0; i < klass->interface_offsets_count; i++) {
+		char *ic_name = mono_type_get_full_name (klass->interfaces_packed [i]);
+		printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s\n", i,
 				klass->interfaces_packed [i]->interface_id,
 				klass->interface_offsets_packed [i],
 				mono_class_get_method_count (klass->interfaces_packed [i]),
-				klass->interfaces_packed [i]->name_space,
-				klass->interfaces_packed [i]->name );
+				ic_name);
+		g_free (ic_name);
+	}
 	printf ("Interface flags: ");
 	for (i = 0; i <= klass->max_interface_id; i++)
 		if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
@@ -2675,6 +2677,55 @@ mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
 	}
 }
 
+static void
+print_vtable_layout_result (MonoClass *klass, MonoMethod **vtable, int cur_slot)
+{
+	int i, icount = 0;
+
+	print_implemented_interfaces (klass);
+
+	for (i = 0; i <= klass->max_interface_id; i++)
+		if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
+			icount++;
+
+	printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (m_class_get_byval_arg (klass)),
+		klass->vtable_size, icount);
+
+	for (i = 0; i < cur_slot; ++i) {
+		MonoMethod *cm;
+
+		cm = vtable [i];
+		if (cm) {
+			printf ("  slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
+				mono_method_full_name (cm, TRUE));
+		} else {
+			printf ("  slot assigned: %03d, <null>\n", i);
+		}
+	}
+
+
+	if (icount) {
+		printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
+			klass->name, klass->max_interface_id);
+
+		for (i = 0; i < klass->interface_count; i++) {
+			MonoClass *ic = klass->interfaces [i];
+			printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
+				mono_class_interface_offset (klass, ic),
+				count_virtual_methods (ic), ic->interface_id, mono_type_full_name (m_class_get_byval_arg (ic)));
+		}
+
+		for (MonoClass *k = klass->parent; k ; k = k->parent) {
+			for (i = 0; i < k->interface_count; i++) {
+				MonoClass *ic = k->interfaces [i]; 
+				printf ("  parent slot offset: %03d, method count: %03d, iid: %03d %s\n",  
+					mono_class_interface_offset (klass, ic),
+					count_virtual_methods (ic), ic->interface_id, mono_type_full_name (m_class_get_byval_arg (ic)));
+			}
+		}
+	}
+}
+
 /*
  * LOCKING: this is supposed to be called with the loader lock held.
  */
@@ -2685,7 +2736,6 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
 	MonoClass *k, *ic;
 	MonoMethod **vtable = NULL;
 	int i, max_vtsize = 0, cur_slot = 0;
-	guint32 max_iid;
 	GPtrArray *ifaces = NULL;
 	GHashTable *override_map = NULL;
 	GHashTable *override_class_map = NULL;
@@ -2747,7 +2797,6 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
 	if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
 		return;
 
-	max_iid = klass->max_interface_id;
 	DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
 
 	/* Optimized version for generic instances */
@@ -2784,6 +2833,9 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
 					klass->methods [i]->slot = gklass->methods [i]->slot;
 		}
 
+		if (mono_print_vtable)
+			print_vtable_layout_result (klass, klass->vtable, gklass->vtable_size);
+
 		return;
 	}
 
@@ -3152,6 +3204,10 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
 				mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
 				g_free (type_name);
 				g_free (method_name);
+
+				if (mono_print_vtable)
+					print_vtable_layout_result (klass, vtable, cur_slot);
+
 				g_free (vtable);
 				return;
 			}
@@ -3183,50 +3239,8 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
 	}
 
 	DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
-	if (mono_print_vtable) {
-		int icount = 0;
-
-		print_implemented_interfaces (klass);
-		
-		for (i = 0; i <= max_iid; i++)
-			if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
-				icount++;
-
-		printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (m_class_get_byval_arg (klass)),
-			klass->vtable_size, icount);
-
-		for (i = 0; i < cur_slot; ++i) {
-			MonoMethod *cm;
-	       
-			cm = vtable [i];
-			if (cm) {
-				printf ("  slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
-					mono_method_full_name (cm, TRUE));
-			}
-		}
-
-
-		if (icount) {
-			printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
-				klass->name, max_iid);
-	
-			for (i = 0; i < klass->interface_count; i++) {
-				ic = klass->interfaces [i];
-				printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
-					mono_class_interface_offset (klass, ic),
-					count_virtual_methods (ic), ic->interface_id, mono_type_full_name (m_class_get_byval_arg (ic)));
-			}
-
-			for (k = klass->parent; k ; k = k->parent) {
-				for (i = 0; i < k->interface_count; i++) {
-					ic = k->interfaces [i]; 
-					printf ("  parent slot offset: %03d, method count: %03d, iid: %03d %s\n",  
-						mono_class_interface_offset (klass, ic),
-						count_virtual_methods (ic), ic->interface_id, mono_type_full_name (m_class_get_byval_arg (ic)));
-				}
-			}
-		}
-	}
+	if (mono_print_vtable)
+		print_vtable_layout_result (klass, vtable, cur_slot);
 
 	g_free (vtable);
 
@@ -3242,6 +3256,10 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
 		mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
 	mono_error_cleanup (error);
 	g_free (name);
+	if (mono_print_vtable)
+		print_vtable_layout_result (klass, vtable, cur_slot);
+
+
 	g_free (vtable);
 	if (override_map)
 		g_hash_table_destroy (override_map);
@@ -4069,7 +4087,7 @@ mono_get_unique_iid (MonoClass *klass)
 		} else {
 			generic_id = 0;
 		}
-		printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
+		printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->assembly_name, type_name, generic_id);
 		g_free (type_name);
 	}
 #endif
diff --git a/mono/metadata/class.c b/mono/metadata/class.c
index 7a39e6197aff..e73324de4c7b 100644
--- a/mono/metadata/class.c
+++ b/mono/metadata/class.c
@@ -644,7 +644,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
 		 * while the VAR/MVAR duplicates a type from the context.  So, we need to ensure that the
 		 * ->byref and ->attrs from @type are propagated to the returned type.
 		 */
-		nt = mono_metadata_type_dup (image, inst->type_argv [num]);
+		nt = mono_metadata_type_dup_with_cmods (image, inst->type_argv [num], type);
 		nt->byref = type->byref;
 		nt->attrs = type->attrs;
 		return nt;
@@ -667,7 +667,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
 				num, pname ? pname : "", inst->type_argv [num]->type);
 			return NULL;			
 		}
-		nt = mono_metadata_type_dup (image, inst->type_argv [num]);
+		nt = mono_metadata_type_dup_with_cmods (image, inst->type_argv [num], type);
 		nt->byref = type->byref;
 		nt->attrs = type->attrs;
 		return nt;
@@ -790,7 +790,7 @@ mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type,
 	if (!inflated) {
 		MonoType *shared = mono_metadata_get_shared_type (type);
 
-		if (shared) {
+		if (shared && !type->has_cmods) {
 			return shared;
 		} else {
 			return mono_metadata_type_dup (image, type);
diff --git a/mono/metadata/metadata-internals.h b/mono/metadata/metadata-internals.h
index 05ceefcc4bfd..18dd66a78a77 100644
--- a/mono/metadata/metadata-internals.h
+++ b/mono/metadata/metadata-internals.h
@@ -894,6 +894,8 @@ void mono_unload_interface_ids (MonoBitSet *bitset);
 
 
 MonoType *mono_metadata_type_dup (MonoImage *image, const MonoType *original);
+MonoType *mono_metadata_type_dup_with_cmods (MonoImage *image, const MonoType *original, const MonoType *cmods_source);
+
 MonoMethodSignature  *mono_metadata_signature_dup_full (MonoImage *image,MonoMethodSignature *sig);
 MonoMethodSignature  *mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig);
 MonoMethodSignature  *mono_metadata_signature_dup_add_this (MonoImage *image, MonoMethodSignature *sig, MonoClass *klass);
diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c
index 4a9586b79217..5fb478a6b62d 100644
--- a/mono/metadata/metadata.c
+++ b/mono/metadata/metadata.c
@@ -5698,13 +5698,28 @@ mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *s
  */
 MonoType *
 mono_metadata_type_dup (MonoImage *image, const MonoType *o)
+{
+	return mono_metadata_type_dup_with_cmods (image, o, o);
+}
+
+/**
+ * Works the same way as mono_metadata_type_dup but pick cmods from @cmods_source
+ */
+MonoType *
+mono_metadata_type_dup_with_cmods (MonoImage *image, const MonoType *o, const MonoType *cmods_source)
 {
 	MonoType *r = NULL;
-	size_t sizeof_o = mono_sizeof_type (o);
+	size_t sizeof_o = mono_sizeof_type (cmods_source);
 
 	r = image ? (MonoType *)mono_image_alloc0 (image, sizeof_o) : (MonoType *)g_malloc (sizeof_o);
 
-	memcpy (r, o, sizeof_o);
+	if (cmods_source->has_cmods) {
+		g_assert (!image || image == mono_type_get_cmods (cmods_source)->image);
+		memcpy (r, cmods_source, sizeof_o);
+	}
+
+	memcpy (r, o, sizeof (MonoType));
+	r->has_cmods = cmods_source->has_cmods;
 
 	if (o->type == MONO_TYPE_PTR) {
 		r->data.type = mono_metadata_type_dup (image, o->data.type);
diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am
index 780acdb545f6..25ee74b34d80 100755
--- a/mono/tests/Makefile.am
+++ b/mono/tests/Makefile.am
@@ -694,7 +694,8 @@ TESTS_CS_SRC=		\
 	nested_type_visibility.cs	\
 	dynamic-method-churn.cs	\
 	verbose.cs \
-	generic-unmanaged-constraint.cs
+	generic-unmanaged-constraint.cs	\
+	bug-10834.cs
 
 # some tests fail to compile on mcs
 if CSC_IS_ROSLYN
diff --git a/mono/tests/bug-10834.cs b/mono/tests/bug-10834.cs
new file mode 100644
index 000000000000..26b07d761196
--- /dev/null
+++ b/mono/tests/bug-10834.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Reflection;
+
+namespace Repro {
+	class Program
+	{
+		static bool Check (Type t)
+		{
+			Console.WriteLine ($"--- {t}");
+
+			var m = t.GetMethod ("M1");
+			Console.WriteLine (m);
+
+			foreach(var p in m.GetParameters ())
+			Console.WriteLine ($"{p}: {p.ParameterType} / {p.GetRequiredCustomModifiers().Length}");
+
+			Console.WriteLine ();
+			return m.GetParameters()[0].GetRequiredCustomModifiers().Length == 1;
+		}
+
+		static int Main(string[] args)
+		{
+			if (!Check (typeof (C<>)))
+				return 1;
+			if (!Check (typeof (C<S1>)))
+				return 2;
+
+			var o = new Bug ();
+			int res = o.M1 (new S1 ());
+			Console.WriteLine (res);
+			if (res != 0)
+				return 3;
+			Console.WriteLine ("All good");
+			return 0;
+		}
+	}
+	abstract class C<U>
+	{
+		public abstract int M1<T>(in T arg) where T : U, I1;
+	}
+
+	class Bug : C<S1>
+	{
+		public override int M1<T2> (in T2 arg)
+		{
+			Console.WriteLine ("C<S1>::M1");
+			arg.M3();
+			return arg.M4();
+		}
+	}
+
+	interface I1
+	{
+		void M3();
+		int M4();
+	}
+
+	public struct S1: I1
+	{
+		public int field;
+		public void M3 ()
+		{
+			Console.WriteLine ("S1:M3");
+			field = 42;
+		}
+
+		public int M4() {
+			Console.WriteLine ("S1:M4 {0}", field);
+			
+			return field;
+		}
+	}
+}
openSUSE Build Service is sponsored by