Bugzilla – Bug 319224
[GMCS] generic interface which has a recursive parameter crashes
Last modified: 2007-09-15 21:24:23 UTC
---- Reported by atsushi@ximian.com 2005-10-07 13:08:44 MST ---- Compile the two lines below: public interface IFoo<T> where T : IFoo<T> { } public interface IBaz<T> where T : IFoo<T> { } Actual Results: Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object in <0x00069> Mono.CSharp.Convert:TypeParam_EffectiveBaseType (Mono.CSharp.EmitContext ec, Mono.CSharp.GenericConstraints gc) in <0x000af> Mono.CSharp.Convert:ImplicitTypeParameterConversion (Mono.CSharp.EmitContext ec, Mono.CSharp.Expression expr, System.Type target_type) in <0x00061> Mono.CSharp.Convert:ImplicitReferenceConversionExists (Mono.CSharp.EmitContext ec, Mono.CSharp.Expression expr, System.Type target_type) in <0x003cd> Mono.CSharp.Convert:ImplicitStandardConversionExists (Mono.CSharp.EmitContext ec, Mono.CSharp.Expression expr, System.Type target_type) in <0x0016f> Mono.CSharp.ConstructedType:CheckConstraint (Mono.CSharp.EmitContext ec, System.Type ptype, Mono.CSharp.Expression expr, System.Type ctype) in <0x00430> Mono.CSharp.ConstructedType:CheckConstraints (Mono.CSharp.EmitContext ec, Int32 index) in <0x00018> Mono.CSharp.ConstructedType:CheckConstraints (Mono.CSharp.EmitContext ec) in <0x00125> Mono.CSharp.Expression:ResolveAsTypeTerminal (Mono.CSharp.EmitContext ec, Boolean silent) in <0x00010> Mono.CSharp.Expression:ResolveAsTypeTerminal (Mono.CSharp.EmitContext ec) in <0x006c7> Mono.CSharp.Constraints:ResolveTypes (Mono.CSharp.EmitContextec) in <0x0001d> Mono.CSharp.TypeParameter:ResolveType (Mono.CSharp.EmitContextec) in <0x00031> Mono.CSharp.TypeParameter:DefineType (Mono.CSharp.EmitContext ec, System.Reflection.Emit.MethodBuilder builder, System.Reflection.MethodInfo implementing, Boolean is_override) in <0x00013> Mono.CSharp.TypeParameter:DefineType (Mono.CSharp.EmitContextec) in <0x00316> Mono.CSharp.TypeContainer:ResolveType () in <0x000dd> Mono.CSharp.RootContext:PopulateTypes () in <0x00b7b> Mono.CSharp.Driver:MainDriver (System.String[] args) in <0x00051> Mono.CSharp.Driver:Main (System.String[] args) Expected Results: no error except for "entrypoint not found". How often does this happen? consistently. Additional Information: - When we remove the second line, it does not happen. - When we remove either of "where" clause, it does not happen. - Such interfaces could make sense e.g. with class Foo : IFoo<Foo> {} class Bar : IFoo<Foo> {} - csc compiles it without error (except for entrypoint stuff). ---- Additional Comments From martin@ximian.com 2005-10-20 00:24:27 MST ---- Backtrace with line numbers: ===== (mdb) frame #0: 0x404b0a29 in Mono.CSharp.Convert.TypeParam_EffectiveBaseType(Mono.CSharp.EmitContext,Mono.CSharp.GenericConstraints)+0x91 at /work/rohan/mono/mcs/gmcs/convert.cs:64 64 foreach (Type t in gc.InterfaceConstraints) { (mdb) bt (*) #0: 0x404b0a29 in Mono.CSharp.Convert.TypeParam_EffectiveBaseType(Mono.CSharp.EmitContext,Mono.CSharp.GenericConstraints)+0x91 at /work/rohan/mono/mcs/gmcs/convert.cs:64 #1: 0x404b072d in Mono.CSharp.Convert.ImplicitTypeParameterConversion(Mono.CSharp.EmitContext,Mono.CSharp.Expression,System.Type)+0xed at /work/rohan/mono/mcs/gmcs/convert.cs:90 #2: 0x404afbfb in Mono.CSharp.Convert.ImplicitReferenceConversionExists(Mono.CSharp.EmitContext,Mono.CSharp.Expression,System.Type)+0x83 at /work/rohan/mono/mcs/gmcs/convert.cs:270 #3: 0x404af552 in Mono.CSharp.Convert.ImplicitStandardConversionExists(Mono.CSharp.EmitContext,Mono.CSharp.Expression,System.Type)+0x86a at /work/rohan/mono/mcs/gmcs/convert.cs:720 #4: 0x404ae182 in Mono.CSharp.ConstructedType.CheckConstraint(Mono.CSharp.EmitContext,System.Type,Mono.CSharp.Expression,System.Type)+0x202 at /work/rohan/mono/mcs/gmcs/generic.cs:1332 #5: 0x404aa87e in Mono.CSharp.ConstructedType.CheckConstraints(Mono.CSharp.EmitContext,System.Int32)+0x64e at /work/rohan/mono/mcs/gmcs/generic.cs:1405 #6: 0x404aa1bb in Mono.CSharp.ConstructedType.CheckConstraints(Mono.CSharp.EmitContext)+0x2b at /work/rohan/mono/mcs/gmcs/generic.cs:1477 #7: 0x404a7a48 in Mono.CSharp.Expression.ResolveAsTypeTerminal(Mono.CSharp.EmitContext,System.Boolean)+0x1d8 at /work/rohan/mono/mcs/gmcs/ecore.cs:272 #8: 0x404a7867 in Mono.CSharp.Expression.ResolveAsTypeTerminal(Mono.CSharp.EmitContext)+0x27 at /work/rohan/mono/mcs/gmcs/ecore.cs:247 #9: 0x404a93f7 in Mono.CSharp.Constraints.ResolveTypes(Mono.CSharp.EmitContext)+0x8ef at /work/rohan/mono/mcs/gmcs/generic.cs:339 #10: 0x404a8aa6 in Mono.CSharp.TypeParameter.ResolveType(Mono.CSharp.EmitContext)+0x2e at /work/rohan/mono/mcs/gmcs/generic.cs:695 #11: 0x404a833b in Mono.CSharp.TypeParameter.DefineType(Mono.CSharp.EmitContext,System.Reflection.Emit.MethodBuilder,System.Reflection.MethodInfo,System.Boolean)+0x7b at /work/rohan/mono/mcs/gmcs/generic.cs:725 #12: 0x404a828e in Mono.CSharp.TypeParameter.DefineType(Mono.CSharp.EmitContext)+0x26 at /work/rohan/mono/mcs/gmcs/generic.cs:712 #13: 0x404a3d80 in Mono.CSharp.TypeContainer.ResolveType()+0x480 at /work/rohan/mono/mcs/gmcs/class.cs:1425 #14: 0x404a2c19 in Mono.CSharp.RootContext.PopulateTypes()+0x169 at /work/rohan/mono/mcs/gmcs/rootcontext.cs:526 #15: 0x40427982 in Mono.CSharp.Driver.MainDriver(System.String[])+0x155a at /work/rohan/mono/mcs/gmcs/driver.cs:1603 #16: 0x40017ed5 in Mono.CSharp.Driver.Main(System.String[])+0xa5 at /work/rohan/mono/mcs/gmcs/driver.cs:287 (mdb) p (Constraints) gc (Mono.CSharp.Constraints) { name = "T", constraints = 0x007dba28, loc = 0x00b8ff50, attrs = None, class_constraint = null, iface_constraints = 0x00834898, type_param_constraints = 0x00834870, num_constraints = 1, class_constraint_type = null, iface_constraint_types = null, effective_base_type = null, resolved = true } (mdb) p ((Constraints) gc).iface_constraints (System.Collections.ArrayList) { _size = 1, _items = Mono.Debugger.Languages.Mono.MonoArrayObject [Mono.Debugger.Languages.Mono.MonoArrayType [System.Object[]]:Mono.Debugger.Languages.Mono.MonoClassType [System.Object]:1], _version = 1 } (mdb) p ((Constraints) gc).iface_constraints [0] (Mono.CSharp.ConstructedType) { "IFoo`1<T>" } ===== ---- Additional Comments From atsushi@ximian.com 2005-10-20 00:44:49 MST ---- The problem is that iface_constraints is null at that time. gmcs misses to call Constraints.Resolve() for IFoo before being used by IBaz (maybe the CheckConstraints() happens during recursive reference?). Am not sure where it should be called though. ---- Additional Comments From martin@ximian.com 2005-10-20 00:50:58 MST ---- `iface_constraint_types' is null, not `iface_constraints'. We need to move this from ResolveTypes() to Resolve() ---- Additional Comments From martin@ximian.com 2005-10-20 00:53:54 MST ---- I have an idea how to fix this, but I'm too tired right now. I'll go to bed and have a look at it when I wake up. ---- Additional Comments From martin@ximian.com 2005-10-21 14:12:13 MST ---- Ok, I think I have a fix for this. We can resolve the types in Constraints.Resolve() and then just check their constraints in Constraints.ResolveTypes(). ---- Additional Comments From martin@ximian.com 2005-10-21 15:04:33 MST ---- Fixed in SVN; added gtest-218.cs. Unknown operating system unknown. Setting to default OS "Other".