Bugzilla – Bug 318987
[GMCS] iterators in generic methods
Last modified: 2007-09-15 21:24:23 UTC
---- Reported by sestoft@dina.kvl.dk 2005-09-14 03:06:49 MST ---- Description of Problem: The gmcs 1.1.9 type checker does not take type parameter constraint Aa : Af into account when checking method body. Steps to reproduce the problem: 1. Compile the program inserted below 2. Observe unexpected compiler error message Actual Results: https://bugzilla.novell.com/show_bug.cgi?id=MONO15.cs(24,20): error CS1594: Delegate `Fun<Af,Rf>' has some invalid arguments https://bugzilla.novell.com/show_bug.cgi?id=MONO15.cs(24,20): error CS1503: Argument 1: Cannot convert from `Aa' to `in Af' Compilation failed: 2 error(s), 0 warnings Expected Results: It should compile without problems, and does in MS beta 2. // ------------------- using System; using System.Collections.Generic; class MyTest { public static void Main(String[] args) { foreach (Object d in Map<int,int,String,Object> (delegate (int x) { return x.ToString(); }, FromTo(10,20))) Console.WriteLine(d); } // Map with argument/result co/contravariance: // Aa=argument, Rr=result, Af=f's argument, Rf=f's result public static IEnumerable<Rr> Map<Aa,Af,Rf,Rr>(Fun<Af,Rf> f, IEnumerable<Aa> xs) where Aa : Af where Rf : Rr { foreach (Aa x in xs) yield return f(x); // gmcs 1.1.9 bug: cannot convert Aa to Af } // FromTo : int * int -> int stream public static IEnumerable<int> FromTo(int from, int to) { for (int i=from; i<=to; i++) yield return i; } } ---- Additional Comments From atsushi@ximian.com 2005-10-19 00:41:20 MST ---- This is the output from csc (beta2). Obviously Foo is missing in the code above. 76097.cs(15,50): error CS0246: The type or namespace name 'Fun' could not be found (are you missing a using directive or an assembly reference?) ---- Additional Comments From sestoft@dina.kvl.dk 2005-10-19 04:36:10 MST ---- Sorry, somehow I neglected to include this declaration: public delegate R Fun<A1,R>(A1 x); ---- Additional Comments From atsushi@ximian.com 2005-10-19 07:19:21 MST ---- Ok, now I got the exception stack trace below: Unhandled Exception: System.NotSupportedException: Operation is not supported. in <0x00014> System.Reflection.Emit.GenericTypeParameterBuilder:GetGenericArguments () in <0x0006d> Mono.CSharp.TypeManager:GetNumberOfTypeArguments (System.Type t) in <0x0000b> Mono.CSharp.TypeManager:HasGenericArguments (System.Type t) in <0x00030> Mono.CSharp.ConstructedType:CheckConstraint (Mono.CSharp.EmitContext ec, System.Type ptype, Mono.CSharp.Expression expr, System.Type ctype) in <0x0042a> 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 <0x00502> Mono.CSharp.Iterator:Create_Block () in <0x000dd> Mono.CSharp.Iterator:DefineNestedTypes () in <0x00b48> Mono.CSharp.TypeContainer:DefineType () in <0x000d8> Mono.CSharp.Class:DefineType () in <0x00834> Mono.CSharp.TypeContainer:DoDefineMembers () in <0x00050> Mono.CSharp.TypeContainer:DefineMembers (Mono.CSharp.TypeContainer container) in <0x0024f> Mono.CSharp.RootContext:PopulateTypes () in <0x00b7b> Mono.CSharp.Driver:MainDriver (System.String[] args) in <0x00051> Mono.CSharp.Driver:Main (System.String[] args) Am attaching a patch that *does not* fix the bug but does fix the exception. ---- Additional Comments From atsushi@ximian.com 2005-10-19 07:20:29 MST ---- Created an attachment (id=168505) a patch that fixes a bug that causes internal exception inside GenericTypeParameterBuilder ---- Additional Comments From martin@ximian.com 2005-10-19 14:13:56 MST ---- Well, that patch is definitely a no-go - of course, just returning an empty list is not an option here. What we need to do for GenericTypeParameterBuilder's is lookup its definition via typemanager; ie. we get the `TypeContainer' which defines its containing class and then lookup the `TypeParameter' for it. I'll have a look at this. ---- Additional Comments From martin@ximian.com 2005-10-19 14:17:23 MST ---- Ooops, I was confused - I tought it was trying to get the constraints from the type parameter. ---- Additional Comments From martin@ximian.com 2005-10-19 14:18:51 MST ---- So the correct fix is in TypeManager.GetNumberOfTypeArguments(): if (t.IsGenericParameter) return 0; ---- Additional Comments From martin@ximian.com 2005-10-19 14:37:06 MST ---- I think I have an idea: ===== (*) #0: 0x404cc329 in Mono.CSharp.TypeManager.GetTypeParameterConstraints(System.Type)+0x59 at /work/gondor/mono/mcs/gmcs/generic.cs:1834 #1: 0x404d8b9e in Mono.CSharp.ConstructedType.CheckConstraint(Mono.CSharp.EmitContext,System.Type,Mono.CSharp.Expression,System.Type)+0x266 at /work/gondor/mono/mcs/gmcs/generic.cs:1305 #2: 0x404b150d in Mono.CSharp.ConstructedType.CheckConstraints(Mono.CSharp.EmitContext,System.Int32)+0x65d at /work/gondor/mono/mcs/gmcs/generic.cs:1386 #3: 0x404b0e3b in Mono.CSharp.ConstructedType.CheckConstraints(Mono.CSharp.EmitContext)+0x2b at /work/gondor/mono/mcs/gmcs/generic.cs:1458 #4: 0x404a6b88 in Mono.CSharp.Expression.ResolveAsTypeTerminal(Mono.CSharp.EmitContext,System.Boolean)+0x1d8 at /work/gondor/mono/mcs/gmcs/ecore.cs:272 #5: 0x404a69a7 in Mono.CSharp.Expression.ResolveAsTypeTerminal(Mono.CSharp.EmitContext)+0x27 at /work/gondor/mono/mcs/gmcs/ecore.cs:247 #6: 0x404d7d36 in Mono.CSharp.Iterator.Create_Block()+0x76e at /work/gondor/mono/mcs/gmcs/iterators.cs:663 #7: 0x404d331d in Mono.CSharp.Iterator.DefineNestedTypes()+0x135 at /work/gondor/mono/mcs/gmcs/iterators.cs:611 #8: 0x404a4863 in Mono.CSharp.TypeContainer.DefineType()+0x112b at /work/gondor/mono/mcs/gmcs/class.cs:1375 #9: 0x404a370d in Mono.CSharp.Class.DefineType()+0x145 at /work/gondor/mono/mcs/gmcs/class.cs:3179 #10: 0x404b3f27 in Mono.CSharp.TypeContainer.DoDefineMembers()+0xb4f at /work/gondor/mono/mcs/gmcs/class.cs:1639 #11: 0x404b330c in Mono.CSharp.TypeContainer.DefineMembers(Mono.CSharp.TypeContainer)+0x64 at /work/gondor/mono/mcs/gmcs/class.cs:1531 #12: 0x404b20df in Mono.CSharp.RootContext.PopulateTypes()+0x357 at /work/gondor/mono/mcs/gmcs/rootcontext.cs:529 #13: 0x40427982 in Mono.CSharp.Driver.MainDriver(System.String[])+0x155a at /work/gondor/mono/mcs/gmcs/driver.cs:1603 #14: 0x40017ed5 in Mono.CSharp.Driver.Main(System.String[])+0xa5 at /work/gondor/mono/mcs/gmcs/driver.cs:287 ===== We're called from RootContext.PopulateTypes(), but still the type parameter's constraints are not defined yet. I believe this is some problem with generic methods and iterators. ---- Additional Comments From martin@ximian.com 2005-10-19 23:40:37 MST ---- Fixed in SVN. Imported an attachment (id=168505) Unknown operating system unknown. Setting to default OS "Other".