Bug 445852

Summary: Mono runtime fails loaded some nested classes
Product: [Mono] Mono: Runtime Reporter: Kevin Hester <khester>
Component: JITAssignee: Paolo Molaro <lupus>
Status: RESOLVED DUPLICATE QA Contact: Mono Bugs <mono-bugs>
Severity: Normal    
Priority: P3 - Medium CC: casey.s.marshall, forgotten_vxPDddArjq
Version: 2.0.x   
Target Milestone: ---   
Hardware: x86-64   
OS: Ubuntu   
Whiteboard:
Found By: Community User Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---
Attachments: A mono/metadata/class.c patch to fix this problem.

Description Kevin Hester 2008-11-17 23:27:05 UTC
Created attachment 252753 [details]
A mono/metadata/class.c patch to fix this problem.

While diagnosing a problem of running F# inside of mono 2.0.1 runtime (official release), I noticed a more fundamental error in how mono is loading nested classes.  

I think I've found the problem and attached a patch to this bug report.

---

If you create an instance of a nested class when the containing class has never been previously referenced, the creation of the inner class fails with the following message:

<FIXME - add message>

The underlying cause of this problem is in metatdata/class.c:mono_class_from_name(<image>, "My.Namespace", "ParentClassName/NestedClassName").   

The parent class is found correctly, but unless some other operation has caused mono_class_init() to be called on 'ParentClass' previously, mono_class_from_name fails to find 'NestedClass'.  I suspect this problem was not previously found, because typically an instance of a parent class is created before it creates/uses/exposes some class that was nested inside itself.  However, because F# hides all functions inside somewhat redundant outer classes (the 'module' in F# speak) this pattern becomes far more common.

My fix is to make class.c/return_nested_in() ensure that the outer class has been inited.  For most (but not all) C# uses this call is a nop because the outer class will already have been inited somewhere else.  If it has not been inited, it must be inited at this point, because mono_class_init is the only thing that populates the nested_classes list that is about to be iterated over.

I can also submit a unit test if you want - I figured I'd create this bug report to get a # assigned at least.
Comment 1 Rodrigo Kumpera 2008-11-18 03:31:06 UTC
Could you please attach a test that shows this bug happening.

Could you attach the IL dump of it as we can't have a test written in F# in our code base.



Comment 2 Rodrigo Kumpera 2008-11-18 12:49:40 UTC
Kevin,

Can you provide such thing?
Comment 3 Kevin Hester 2008-11-18 18:53:17 UTC
Sure thing - not until next week though (I have some other things in my queue).

The problem isn't so much F# as it is an error in the mono embedding API call for mono_class_from_name.  That function doesn't work correctly with nested classes unless someone has already called class_init on the outer class.

This problem doesn't show for non embedded applications because the regular Type.GetType() call goes through a static function called mono_reflection_get_type_internal which is careful to ensure that outer classes are resolved.

Are there any existing test cases for the embedding API?  It would probably be easier for me to extend one of those.  I couldn't find any.

Comment 4 Casey Marshall 2008-11-18 19:37:59 UTC
Can we work around this by doing more in the code that embeds mono? That is, are there hoops we just have to jump through -- like try to load outer types first ourselves, if we encounter an inner type -- to make this work?
Comment 5 Rodrigo Kumpera 2008-11-18 22:51:35 UTC
Guys,

The proper fix is to apply r111499.

This is not a regression and 2.2 is going to be released in about a month from now with the fix, so I'm not willing to risk backporting the fix unless it's really needed.

Comment 6 Rodrigo Kumpera 2008-11-18 22:51:55 UTC

*** This bug has been marked as a duplicate of bug 418433 ***