Bugzilla – Bug 318251
[GMCS]junk read by reflection for nested generic types
Last modified: 2007-09-15 21:24:46 UTC
---- Reported by malekith@pld-linux.org 2005-06-13 07:26:33 MST ---- Description of Problem: When you define a nested generic type inside another generic type, mono's reflection takes !1 as a reference to wrong type parameter (namely the one from nested class not the global class). For the following piece of Nemerle code: interface IComp ['a] { } class opt ['c] { } abstract class Func [p1, r] { public apply (x : p1) : r { throw System.Exception () } } class NemerleMap ['a, 'b] where 'a : IComp ['a] { public Find (k : 'a) : opt ['b] { null } public Fold['d] (y : 'a) : void { def x = lambda (); _ = x.apply (y); } class lambda [d, aa, bb] : Func [aa, aa] where aa : IComp [aa] { public apply2 (x : aa) : aa { x; } } } after compiling it to a dll reflection says that return type of Find is opt<aa> and not opt<'b>. monodis handles it right, ms.net reflection, peverify and ildasm are also all OK with this. Steps to reproduce the problem: 1. untar attachment 2. compile and run attached C# program for reading assembly Actual Results: opt<aa> Expected Results: opt<'b> Additional Information: I'm using svn trunk. ---- Additional Comments From malekith@pld-linux.org 2005-06-13 07:27:27 MST ---- Created an attachment (id=168123) testcase ---- Additional Comments From nazgul@omega.pl 2005-06-13 13:45:53 MST ---- After a little debugging I found out that there is some serious data invariants violation in runtime. The bug occurs, because in mono_metadata_lookup_generic_inst the incorrect cache value is returned: (gdb) p ginst->type_argv[0]->data.generic_param.name $4 = 0xb752a748 "'b" (gdb) p cached $5 = (MonoGenericInst *) 0x8274df8 (gdb) p cached -> type_argv[0]->data.generic_param.name $6 = 0xb752a74d "aa" indeed their metadata used in hashtable compare are the same: (gdb) p cached -> type_argv[0]->data.generic_param.owner $7 = (MonoGenericContainer *) 0x8274850 (gdb) p ginst->type_argv[0]->data.generic_param.owner $8 = (MonoGenericContainer *) 0x8274850 but evidently the value already in cache have wrong generic context attached: (gdb) p cached -> type_argv[0]->data.generic_param.owner->klass->name $10 = 0xb752a708 "NemerleMap" (gdb) p cached -> type_argv[0]->data.generic_param.name $11 = 0xb752a74d "aa" I dunno where it gets such context... ---- Additional Comments From martin@ximian.com 2005-06-15 15:41:36 MST ---- The `out.exe' has an incorrect nested class - it's missing the type parameters from the containing class. Since this is a violation of the spec and it'd require a lot of work, let's close this as WONTFIX. ---- Additional Comments From martin@ximian.com 2005-06-15 15:42:06 MST ---- Equivalent C# test case: ===== interface IComp<a> { } class opt<c> { } abstract class Func<p1,r> { public r apply (p1 x) { throw new System.Exception (); } } class NemerleMap<a,b> where a : IComp<a> { public opt<b> Find (a k) { return null; } public void Fold<d> (a y) { } class lambda<d,aa,bb> : Func<aa,aa> where aa : IComp<aa> { public aa apply2 (aa x) { return x; } } } ==== ---- Additional Comments From martin@ximian.com 2005-06-15 15:43:25 MST ---- Note that this is encoded in IL as: ==== .class private auto ansi beforefieldinit NemerleMap`2<(class IComp`1<!a>) a,b> extends [mscorlib]System.Object { .class auto ansi nested private beforefieldinit lambda`3<(class IComp`1<!a>) a,b,d,(class IComp`1<!aa>) aa, bb> extends class Func`2<!aa,!aa> ==== when compiled with csc - ie. the nested class inherits the type parameters of its parent. ---- Additional Comments From malekith@pld-linux.org 2005-06-16 05:39:31 MST ---- Is it violation of C# spec or IL/metadata spec? Anyway we had the type parameters copied by at the end not at the beginning of the parameter list, so I'll just fix it on our side. Imported an attachment (id=168123) Unknown bug field "cf_op_sys_details" encountered while moving bug <cf_op_sys_details>amd 64 pld linux</cf_op_sys_details> Unknown operating system unknown. Setting to default OS "Other".