Bugzilla – Bug 320713
[GMCS] NRE on class X : Y<X.Z> - derived class of a generic type whose generic argument is its nested child class
Last modified: 2007-09-15 21:24:23 UTC
---- Reported by atsushi@ximian.com 2006-03-30 15:11:58 MST ---- The example code below causes NullReferenceException due to incomplete type resolution. Bar is derived from a generic class whose generic argument is the nested child class of Bar (i.e. Bar.Baz). public class Foo<K> { } public class Bar : Foo<Bar.Baz> { public class Baz { } } Actual Results: Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object in <0x00169> Mono.CSharp.TypeContainer:DoDefineMembers () in <0x0004a> Mono.CSharp.TypeContainer:DefineMembers () in <0x0023f> Mono.CSharp.RootContext:PopulateTypes () in <0x00e23> Mono.CSharp.Driver:MainDriver (System.String[] args) in <0x00056> Mono.CSharp.Driver:Main (System.String[] args) Expected Results: no such error. How often does this happen? consistently. Additional Information: This blocks a production-ready game SDK library which works with mono. http://yanesdkdotnet.sourceforge.jp/ , src/draw/BitmapLoader.cs ---- Additional Comments From atsushi@ximian.com 2006-03-30 20:16:59 MST ---- Created an attachment (id=169516) Workaround patch (I'm not attaching it for mcs hackers but those who really need to avoid this problem) ---- Additional Comments From atsushi@ximian.com 2006-06-21 02:21:21 MST ---- Now one of Ruby.NET (Gardens Point Ruby.NET Compiler) hits the same problem http://www.plas.fit.qut.edu.au/Ruby.NET/ ---- Additional Comments From martin@ximian.com 2006-06-21 09:56:27 MST ---- Possible duplicate of #77396. ---- Additional Comments From miguel@ximian.com 2006-07-02 10:51:44 MST ---- Am upping the priority ---- Additional Comments From martin@ximian.com 2006-07-03 08:12:51 MST ---- Increasing the priority doesn't help here - look at the dependency graph. ---- Additional Comments From rharinath@novell.com 2006-08-02 10:45:01 MST ---- Should be fixed in SVN r63251. ---- Additional Comments From jan.oravec@6com.sk 2006-09-01 20:20:17 MST ---- The more generic variation of this still doesn't work (current SVN): public class Foo<K> { } public class Bar<Q> : Foo<Bar<Q>.Baz> { public class Baz { } } a.cs(5,27): error CS0426: The nested type `Baz' does not exist in the type `Bar<Q>' Compilation failed: 1 error(s), 0 warnings The similar example not involving cyclic dependency (Bar -> Foo<Baz> -> Baz -> Bar) works fine: public class Foo<K> { } public class Bar<Q> { public class Baz { } } public class Goo<Q> : Foo<Bar<Q>.Baz> { } Closing the cycle again with: public class Foo<K> { } public class Bar<Q> : Goo<Q> { public class Baz { } } public class Goo<Q> : Foo<Bar<Q>.Baz> { } Fails again with: c.cs(12,27): error CS0426: The nested type `Baz' does not exist in the type `Bar<Q>' Compilation failed: 1 error(s), 0 warnings ---- Additional Comments From jan.oravec@6com.sk 2006-09-01 23:20:35 MST ---- I think I have found where is the problem. We are resolving Foo<Bar<Q>.Baz> in the context of Bar`1[Q] instead of just Bar`1. If I understand it right, TypeExpression denotes Bar`1, while ConstructedType denotes Bar`1[Q]. The code was not passing TypeBuilder to the MemberLookup and then to the MemberLookup_FindMembers, thus weren't able to find Baz there. This is first time I were looking at the gmcs source. I do not know the terminology, etc., but I think that ResolveAsTypeTerminal was supposed to get the TypeExpression from the ConstructedType, which is called at ResolveNamespaceOrType. Thus I overloaded ResolveAsTypeTerminal in ConstructedType. Please see the attached patch. I am not sure if I am right, it may be horribly wrong :). I have tested it and it appears to work and produce correct code. ---- Additional Comments From jan.oravec@6com.sk 2006-09-01 23:22:14 MST ---- Created an attachment (id=169517) Fix for the case of nested type inside generic type ---- Additional Comments From jan.oravec@6com.sk 2006-09-02 21:01:11 MST ---- My patch still doesn't work when constraints are added to the Bar<Q>, e.g.: public class Foo<K> { } public class Bar<Q> : Foo<Bar<Q>.Baz> where Q : System.IEquatable<Q> { public class Baz { } } Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object at Mono.CSharp.Constraints.ResolveTypes (IResolveContext ec) [0x00000] at Mono.CSharp.TypeParameter.ResolveType (IResolveContext ec) [0x00000] at Mono.CSharp.TypeParameter.DefineType (IResolveContext ec, System.Reflection.Emit.MethodBuilder builder, System.Reflection.MethodInfo implementing, Boolean is_override) [0x00000] at Mono.CSharp.TypeParameter.DefineType (IResolveContext ec) [0x00000] at Mono.CSharp.TypeContainer.ResolveType () [0x00000] at Mono.CSharp.RootContext.PopulateTypes () [0x00000] at Mono.CSharp.Driver.MainDriver (System.String[] args) [0x00000] at Mono.CSharp.Driver.Main (System.String[] args) [0x00000] Seems like ResolveTypes() was called before Resolve(). A quick hack "if(!resolved) Resolve();" in the begin of ResolveTypes() appears to work. When this is fixed the correct way, I would propose adding assertions to such places. ---- Additional Comments From jan.oravec@6com.sk 2006-09-03 15:41:25 MST ---- I had found some time to look deeper inside the compiler code. I realized this: We are constructing type Bar`1[Q] from Bar`1 when Bar`1 is not yet fully built, so we need either: - drop requirement for constructing type Bar`1[Q] until we have Bar`1 fully built, or - build Bar`1[Q] together with Bar`1 (does Reflexion handle this automagically for us when we change Bar`1? looks like it doesn't) ---- Additional Comments From rharinath@novell.com 2006-10-18 18:29:12 MST ---- There are several hacks in the compiler because of this. Fixing this issue properly will require a fair amount of refactoring, that is anyway planned for other reasons including code hygiene. Otherwise, we need some more DropGenericArguments in strategic locations. ---- Additional Comments From martin@ximian.com 2007-03-20 18:51:49 MST ---- Fixed in SVN; added gtest-317.cs and gtest-318.cs. ---- Additional Comments From martin@ximian.com 2007-03-20 18:52:25 MST ---- *** https://bugzilla.novell.com/show_bug.cgi?id=MONO80314 has been marked as a duplicate of this bug. *** ---- Additional Comments From martin@ximian.com 2007-03-20 18:53:44 MST ---- *** https://bugzilla.novell.com/show_bug.cgi?id=MONO81019 has been marked as a duplicate of this bug. *** ---- Additional Comments From jan.oravec@6com.sk 2007-03-21 06:15:56 MST ---- Thanks! This bug depended on bug(s) 77396 77403. Imported an attachment (id=169516) Imported an attachment (id=169517) Unknown operating system unknown. Setting to default OS "Other".