2004-04-02 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / gmcs / generic.cs
1 //
2 // generic.cs: Support classes for generics
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2003 Ximian, Inc.
8 //
9 using System;
10 using System.Reflection;
11 using System.Reflection.Emit;
12 using System.Globalization;
13 using System.Collections;
14 using System.Text;
15         
16 namespace Mono.CSharp {
17
18         //
19         // Tracks the constraints for a type parameter
20         //
21         public class Constraints : GenericConstraints {
22                 string name;
23                 ArrayList constraints;
24                 Location loc;
25                 
26                 //
27                 // name is the identifier, constraints is an arraylist of
28                 // Expressions (with types) or `true' for the constructor constraint.
29                 // 
30                 public Constraints (string name, ArrayList constraints,
31                                     Location loc)
32                 {
33                         this.name = name;
34                         this.constraints = constraints;
35                         this.loc = loc;
36                 }
37
38                 public string TypeParameter {
39                         get {
40                                 return name;
41                         }
42                 }
43
44                 bool has_ctor_constraint;
45                 TypeExpr class_constraint;
46                 ArrayList iface_constraints;
47                 TypeExpr[] constraint_types;
48                 int num_constraints, first_constraint;
49                 Type[] types;
50
51                 public bool HasConstructorConstraint {
52                         get { return has_ctor_constraint; }
53                 }
54
55                 public bool Resolve (DeclSpace ds)
56                 {
57                         iface_constraints = new ArrayList ();
58
59                         foreach (object obj in constraints) {
60                                 if (has_ctor_constraint) {
61                                         Report.Error (401, loc,
62                                                       "The new() constraint must be last.");
63                                         return false;
64                                 }
65
66                                 if (obj is bool) {
67                                         has_ctor_constraint = true;
68                                         continue;
69                                 }
70
71                                 TypeExpr expr = ds.ResolveTypeExpr ((Expression) obj, false, loc);
72                                 if (expr == null)
73                                         return false;
74
75                                 if (expr is TypeParameterExpr) {
76                                         Report.Error (700, loc,
77                                                       "`{0}': naked type parameters cannot " +
78                                                       "be used as bounds", expr.Name);
79                                         return false;
80                                 }
81
82                                 if (expr.IsInterface)
83                                         iface_constraints.Add (expr);
84                                 else if (class_constraint != null) {
85                                         Report.Error (406, loc,
86                                                       "`{0}': the class constraint for `{1}' " +
87                                                       "must come before any other constraints.",
88                                                       expr.Name, name);
89                                         return false;
90                                 } else
91                                         class_constraint = expr;
92
93                                 num_constraints++;
94                         }
95
96                         constraint_types = new TypeExpr [num_constraints];
97                         if (class_constraint != null)
98                                 constraint_types [first_constraint++] = class_constraint;
99                         iface_constraints.CopyTo (constraint_types, first_constraint);
100
101                         return true;
102                 }
103
104                 public Type[] ResolveTypes (EmitContext ec)
105                 {
106                         types = new Type [constraint_types.Length];
107
108                         for (int i = 0; i < constraint_types.Length; i++) {
109                                 types [i] = constraint_types [i].ResolveType (ec);
110                                 if (types [i] == null)
111                                         return null;
112
113                                 for (int j = first_constraint; j < i; j++) {
114                                         if (!types [j].Equals (types [i]))
115                                                 continue;
116
117                                         Report.Error (405, loc,
118                                                       "Duplicate constraint `{0}' for type " +
119                                                       "parameter `{1}'.", types [i], name);
120                                         return null;
121                                 }
122                         }
123
124                         if (class_constraint != null) {
125                                 if (types [0].IsSealed) {
126                                         Report.Error (701, loc,
127                                                       "`{0}' is not a valid bound.  Bounds " +
128                                                       "must be interfaces or non sealed " +
129                                                       "classes", types [0]);
130                                         return null;
131                                 }
132
133                                 if ((types [0] == TypeManager.array_type) ||
134                                     (types [0] == TypeManager.delegate_type) ||
135                                     (types [0] == TypeManager.enum_type) ||
136                                     (types [0] == TypeManager.value_type) ||
137                                     (types [0] == TypeManager.object_type)) {
138                                         Report.Error (702, loc,
139                                                       "Bound cannot be special class `{0}'",
140                                                       types [0]);
141                                         return null;
142                                 }
143                         }
144
145                         return types;
146                 }
147
148                 bool GenericConstraints.HasConstructor {
149                         get {
150                                 return has_ctor_constraint;
151                         }
152                 }
153
154                 Type[] GenericConstraints.Types {
155                         get {
156                                 if (types == null)
157                                         throw new InvalidOperationException ();
158
159                                 return types;
160                         }
161                 }
162         }
163
164         //
165         // This type represents a generic type parameter
166         //
167         public class TypeParameter {
168                 string name;
169                 Constraints constraints;
170                 Location loc;
171                 Type type;
172
173                 public TypeParameter (string name, Constraints constraints, Location loc)
174                 {
175                         this.name = name;
176                         this.constraints = constraints;
177                         this.loc = loc;
178                 }
179
180                 public string Name {
181                         get {
182                                 return name;
183                         }
184                 }
185
186                 public Location Location {
187                         get {
188                                 return loc;
189                         }
190                 }
191
192                 public Constraints Constraints {
193                         get {
194                                 return constraints;
195                         }
196                 }
197
198                 public bool HasConstructorConstraint {
199                         get {
200                                 if (constraints != null)
201                                         return constraints.HasConstructorConstraint;
202
203                                 return false;
204                         }
205                 }
206
207                 public Type Type {
208                         get {
209                                 return type;
210                         }
211                 }
212
213                 public bool Resolve (DeclSpace ds)
214                 {
215                         if (constraints != null)
216                                 return constraints.Resolve (ds);
217
218                         return true;
219                 }
220
221                 public Type Define (TypeBuilder tb)
222                 {
223                         type = tb.DefineGenericParameter (name);
224                         TypeManager.AddTypeParameter (type, this);
225                         return type;
226                 }
227
228                 public Type DefineMethod (MethodBuilder mb)
229                 {
230                         type = mb.DefineGenericParameter (name);
231                         TypeManager.AddTypeParameter (type, this);
232                         return type;
233                 }
234
235                 public bool DefineType (EmitContext ec, TypeBuilder tb)
236                 {
237                         int index = type.GenericParameterPosition;
238                         if (constraints == null)
239                                 tb.SetGenericParameterConstraints (index, new Type [0], false);
240                         else {
241                                 Type[] types = constraints.ResolveTypes (ec);
242                                 if (types == null)
243                                         return false;
244
245                                 tb.SetGenericParameterConstraints (
246                                         index, types, constraints.HasConstructorConstraint);
247                         }
248
249                         return true;
250                 }
251
252                 public bool DefineType (EmitContext ec, MethodBuilder mb)
253                 {
254                         int index = type.GenericParameterPosition;
255                         if (constraints == null)
256                                 mb.SetGenericParameterConstraints (index, new Type [0], false);
257                         else {
258                                 Type[] types = constraints.ResolveTypes (ec);
259                                 if (types == null)
260                                         return false;
261
262                                 mb.SetGenericParameterConstraints (
263                                         index, types, constraints.HasConstructorConstraint);
264                         }
265
266                         return true;
267                 }
268
269                 public override string ToString ()
270                 {
271                         return "TypeParameter[" + name + "]";
272                 }
273         }
274
275         //
276         // This type represents a generic type parameter reference.
277         //
278         // These expressions are born in a fully resolved state.
279         //
280         public class TypeParameterExpr : TypeExpr {
281                 TypeParameter type_parameter;
282
283                 public override string Name {
284                         get {
285                                 return type_parameter.Name;
286                         }
287                 }
288
289                 public TypeParameter TypeParameter {
290                         get {
291                                 return type_parameter;
292                         }
293                 }
294                 
295                 public TypeParameterExpr (TypeParameter type_parameter, Location loc)
296                 {
297                         this.type_parameter = type_parameter;
298                         this.loc = loc;
299                 }
300
301                 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
302                 {
303                         type = type_parameter.Type;
304
305                         return this;
306                 }
307
308                 public void Error_CannotUseAsUnmanagedType (Location loc)
309                 {
310                         Report.Error (-203, loc, "Can not use type parameter as unamanged type");
311                 }
312         }
313
314         public class TypeArguments {
315                 public readonly Location Location;
316                 ArrayList args;
317                 Type[] atypes;
318                 bool has_type_args;
319                 bool created;
320                 
321                 public TypeArguments (Location loc)
322                 {
323                         args = new ArrayList ();
324                         this.Location = loc;
325                 }
326
327                 public void Add (Expression type)
328                 {
329                         if (created)
330                                 throw new InvalidOperationException ();
331
332                         args.Add (type);
333                 }
334
335                 public void Add (TypeArguments new_args)
336                 {
337                         if (created)
338                                 throw new InvalidOperationException ();
339
340                         args.AddRange (new_args.args);
341                 }
342
343                 public string[] GetDeclarations ()
344                 {
345                         string[] ret = new string [args.Count];
346                         for (int i = 0; i < args.Count; i++) {
347                                 SimpleName sn = args [i] as SimpleName;
348                                 if (sn != null) {
349                                         ret [i] = sn.Name;
350                                         continue;
351                                 }
352
353                                 Report.Error (81, Location, "Type parameter declaration " +
354                                               "must be an identifier not a type");
355                                 return null;
356                         }
357                         return ret;
358                 }
359
360                 public Type[] Arguments {
361                         get {
362                                 return atypes;
363                         }
364                 }
365
366                 public bool HasTypeArguments {
367                         get {
368                                 return has_type_args;
369                         }
370                 }
371
372                 public int Count {
373                         get {
374                                 return args.Count;
375                         }
376                 }
377
378                 public override string ToString ()
379                 {
380                         StringBuilder s = new StringBuilder ();
381
382                         int count = args.Count;
383                         for (int i = 0; i < count; i++){
384                                 //
385                                 // FIXME: Use TypeManager.CSharpname once we have the type
386                                 //
387                                 s.Append (args [i].ToString ());
388                                 if (i+1 < count)
389                                         s.Append (",");
390                         }
391                         return s.ToString ();
392                 }
393
394                 public bool Resolve (EmitContext ec)
395                 {
396                         DeclSpace ds = ec.DeclSpace;
397                         int count = args.Count;
398                         bool ok = true;
399
400                         atypes = new Type [count];
401                         
402                         for (int i = 0; i < count; i++){
403                                 TypeExpr te = ds.ResolveTypeExpr (
404                                         (Expression) args [i], false, Location);
405                                 if (te == null) {
406                                         ok = false;
407                                         continue;
408                                 }
409                                 if (te is TypeParameterExpr)
410                                         has_type_args = true;
411                                 atypes [i] = te.ResolveType (ec);
412
413                                 if (atypes [i] == null) {
414                                         Report.Error (246, Location, "Cannot find type `{0}'",
415                                                       te.Name);
416                                         ok = false;
417                                 }
418                         }
419                         return ok;
420                 }
421         }
422         
423         public class ConstructedType : TypeExpr {
424                 string name, full_name;
425                 TypeArguments args;
426                 Type[] gen_params, atypes;
427                 Type gt;
428                 
429                 public ConstructedType (string name, TypeArguments args, Location l)
430                 {
431                         loc = l;
432                         this.name = name;
433                         this.args = args;
434
435                         eclass = ExprClass.Type;
436                         full_name = name + "<" + args.ToString () + ">";
437                 }
438
439                 public ConstructedType (string name, TypeParameter[] type_params, Location l)
440                         : this (type_params, l)
441                 {
442                         loc = l;
443
444                         this.name = name;
445                         full_name = name + "<" + args.ToString () + ">";
446                 }
447
448                 protected ConstructedType (TypeArguments args, Location l)
449                 {
450                         loc = l;
451                         this.args = args;
452
453                         eclass = ExprClass.Type;
454                 }
455
456                 protected ConstructedType (TypeParameter[] type_params, Location l)
457                 {
458                         loc = l;
459
460                         args = new TypeArguments (l);
461                         foreach (TypeParameter type_param in type_params)
462                                 args.Add (new TypeParameterExpr (type_param, l));
463
464                         eclass = ExprClass.Type;
465                 }
466
467                 public ConstructedType (Type t, TypeParameter[] type_params, Location l)
468                         : this (type_params, l)
469                 {
470                         gt = t.GetGenericTypeDefinition ();
471
472                         this.name = gt.FullName;
473                         full_name = gt.FullName + "<" + args.ToString () + ">";
474                 }
475
476                 public ConstructedType (Type t, TypeArguments args, Location l)
477                         : this (args, l)
478                 {
479                         gt = t.GetGenericTypeDefinition ();
480
481                         this.name = gt.FullName;
482                         full_name = gt.FullName + "<" + args.ToString () + ">";
483                 }
484
485                 public TypeArguments TypeArguments {
486                         get { return args; }
487                 }
488
489                 protected string DeclarationName {
490                         get {
491                                 StringBuilder sb = new StringBuilder ();
492                                 sb.Append (gt.FullName);
493                                 sb.Append ("<");
494                                 for (int i = 0; i < gen_params.Length; i++) {
495                                         if (i > 0)
496                                                 sb.Append (",");
497                                         sb.Append (gen_params [i]);
498                                 }
499                                 sb.Append (">");
500                                 return sb.ToString ();
501                         }
502                 }
503
504                 protected bool CheckConstraints (EmitContext ec, int index)
505                 {
506                         Type atype = atypes [index];
507                         Type ptype = gen_params [index];
508
509                         if (atype == ptype)
510                                 return true;
511
512                         Expression aexpr = new EmptyExpression (atype);
513
514                         //
515                         // First, check the class constraint.
516                         //
517
518                         Type parent = ptype.BaseType;
519                         if ((parent != null) && (parent != TypeManager.object_type)) {
520                                 if (!Convert.ImplicitStandardConversionExists (aexpr, parent)) {
521                                         Report.Error (309, loc, "The type `{0}' must be " +
522                                                       "convertible to `{1}' in order to " +
523                                                       "use it as parameter `{2}' in the " +
524                                                       "generic type or method `{3}'",
525                                                       atype, parent, ptype, DeclarationName);
526                                         return false;
527                                 }
528                         }
529
530                         //
531                         // Now, check the interface constraints.
532                         //
533                         foreach (Type itype in ptype.GetInterfaces ()) {
534                                 if (!Convert.ImplicitStandardConversionExists (aexpr, itype)) {
535                                         Report.Error (309, loc, "The type `{0}' must be " +
536                                                       "convertible to `{1}' in order to " +
537                                                       "use it as parameter `{2}' in the " +
538                                                       "generic type or method `{3}'",
539                                                       atype, itype, ptype, DeclarationName);
540                                         return false;
541                                 }
542                         }
543
544                         //
545                         // Finally, check the constructor constraint.
546                         //
547
548                         if (!TypeManager.HasConstructorConstraint (ptype))
549                                 return true;
550
551                         MethodGroupExpr mg = Expression.MemberLookup (
552                                 ec, atype, ".ctor", MemberTypes.Constructor,
553                                 BindingFlags.Public | BindingFlags.Instance |
554                                 BindingFlags.DeclaredOnly, loc)
555                                 as MethodGroupExpr;
556
557                         if (atype.IsAbstract || (mg == null) || !mg.IsInstance) {
558                                 Report.Error (310, loc, "The type `{0}' must have a public " +
559                                               "parameterless constructor in order to use it " +
560                                               "as parameter `{1}' in the generic type or " +
561                                               "method `{2}'", atype, ptype, DeclarationName);
562                                 return false;
563                         }
564
565                         return true;
566                 }
567
568                 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
569                 {
570                         if (gt != null)
571                                 return this;
572
573                         //
574                         // First, resolve the generic type.
575                         //
576                         DeclSpace ds;
577                         Type nested = ec.DeclSpace.FindNestedType (loc, name, out ds);
578                         if (nested != null) {
579                                 gt = nested.GetGenericTypeDefinition ();
580
581                                 TypeArguments new_args = new TypeArguments (loc);
582                                 foreach (TypeParameter param in ds.TypeParameters)
583                                         new_args.Add (new TypeParameterExpr (param, loc));
584                                 new_args.Add (args);
585
586                                 args = new_args;
587                                 return this;
588                         }
589
590                         Type t;
591                         int num_args;
592
593                         SimpleName sn = new SimpleName (name, args.Count, loc);
594                         TypeExpr resolved = sn.ResolveAsTypeTerminal (ec);
595                         if (resolved == null) {
596                                 sn = new SimpleName (name, -1, loc);
597                                 resolved = sn.ResolveAsTypeTerminal (ec);
598                                 if ((resolved == null) || (resolved.Type == null)) {
599                                         Report.Error (246, loc,
600                                                       "The type or namespace name `{0}<...>' "+
601                                                       "could not be found", name);
602                                         return null;
603                                 }
604
605                                 t = resolved.Type;
606                                 num_args = TypeManager.GetNumberOfTypeArguments (t);
607
608                                 if (num_args == 0) {
609                                         Report.Error (308, loc,
610                                                       "The non-generic type `{0}' cannot " +
611                                                       "be used with type arguments.",
612                                                       TypeManager.CSharpName (t));
613                                         return null;
614                                 }
615
616                                 Report.Error (305, loc,
617                                               "Using the generic type `{0}' " +
618                                               "requires {1} type arguments",
619                                               TypeManager.GetFullName (t), num_args);
620                                 return null;
621                         }
622
623                         t = resolved.Type;
624                         if (t == null) {
625                                 Report.Error (246, loc, "Cannot find type `{0}'", full_name);
626                                 return null;
627                         }
628
629                         num_args = TypeManager.GetNumberOfTypeArguments (t);
630                         if (num_args == 0) {
631                                 Report.Error (308, loc,
632                                               "The non-generic type `{0}' cannot " +
633                                               "be used with type arguments.",
634                                               TypeManager.CSharpName (t));
635                                 return null;
636                         }
637
638                         gt = t.GetGenericTypeDefinition ();
639                         return this;
640                 }
641
642                 public override Type ResolveType (EmitContext ec)
643                 {
644                         if (type != null)
645                                 return type;
646                         if (DoResolveAsTypeStep (ec) == null)
647                                 return null;
648
649                         //
650                         // Resolve the arguments.
651                         //
652                         if (args.Resolve (ec) == false)
653                                 return null;
654
655                         gen_params = gt.GetGenericArguments ();
656                         atypes = args.Arguments;
657
658                         if (atypes.Length != gen_params.Length) {
659                                 Report.Error (305, loc,
660                                               "Using the generic type `{0}' " +
661                                               "requires {1} type arguments",
662                                               TypeManager.GetFullName (gt),
663                                               gen_params.Length);
664                                 return null;
665                         }
666
667                         for (int i = 0; i < gen_params.Length; i++) {
668                                 if (!CheckConstraints (ec, i))
669                                         return null;
670                         }
671
672                         //
673                         // Now bind the parameters.
674                         //
675                         type = gt.BindGenericParameters (atypes);
676                         return type;
677                 }
678
679                 public Expression GetMemberAccess (EmitContext ec)
680                 {
681                         TypeExpr current;
682                         if (ec.TypeContainer.CurrentType != null)
683                                 current = ec.TypeContainer.CurrentType;
684                         else
685                                 current = new TypeExpression (ec.ContainerType, loc);
686
687                         return new GenericMemberAccess (current, name, args, loc);
688                 }
689
690                 public override bool CheckAccessLevel (DeclSpace ds)
691                 {
692                         return ds.CheckAccessLevel (gt);
693                 }
694
695                 public override bool AsAccessible (DeclSpace ds, int flags)
696                 {
697                         return ds.AsAccessible (gt, flags);
698                 }
699
700                 public override bool IsClass {
701                         get { return gt.IsClass; }
702                 }
703
704                 public override bool IsValueType {
705                         get { return gt.IsValueType; }
706                 }
707
708                 public override bool IsInterface {
709                         get { return gt.IsInterface; }
710                 }
711
712                 public override bool IsSealed {
713                         get { return gt.IsSealed; }
714                 }
715
716                 public override bool IsAttribute {
717                         get { return false; }
718                 }
719
720                 public override TypeExpr[] GetInterfaces ()
721                 {
722                         TypeExpr[] ifaces = TypeManager.GetInterfaces (gt);
723                         return ifaces;
724                 }
725
726                 public override bool Equals (object obj)
727                 {
728                         ConstructedType cobj = obj as ConstructedType;
729                         if (cobj == null)
730                                 return false;
731
732                         if ((type == null) || (cobj.type == null))
733                                 return false;
734
735                         return type == cobj.type;
736                 }
737
738                 public override string Name {
739                         get {
740                                 return full_name;
741                         }
742                 }
743         }
744
745         public class GenericMethod : DeclSpace
746         {
747                 public GenericMethod (NamespaceEntry ns, TypeContainer parent, string name,
748                                       Attributes attrs, Location l)
749                         : base (ns, parent, name, attrs, l)
750                 { }
751
752                 public override TypeBuilder DefineType ()
753                 {
754                         throw new Exception ();
755                 }
756
757                 public override bool Define (TypeContainer parent)
758                 {
759                         for (int i = 0; i < TypeParameters.Length; i++)
760                                 if (!TypeParameters [i].Resolve (parent))
761                                         return false;
762
763                         return true;
764                 }
765
766                 public bool Define (TypeContainer parent, MethodBuilder mb)
767                 {
768                         if (!Define (parent))
769                                 return false;
770
771                         Type[] gen_params = new Type [TypeParameters.Length];
772                         for (int i = 0; i < TypeParameters.Length; i++)
773                                 gen_params [i] = TypeParameters [i].DefineMethod (mb);
774
775                         return true;
776                 }
777
778                 public bool DefineType (EmitContext ec, MethodBuilder mb)
779                 {
780                         for (int i = 0; i < TypeParameters.Length; i++)
781                                 if (!TypeParameters [i].DefineType (ec, mb))
782                                         return false;
783
784                         return true;
785                 }
786
787                 public override bool DefineMembers (TypeContainer parent)
788                 {
789                         return true;
790                 }
791
792                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
793                                                         MemberFilter filter, object criteria)
794                 {
795                         throw new Exception ();
796                 }               
797
798                 public override MemberCache MemberCache {
799                         get {
800                                 throw new Exception ();
801                         }
802                 }
803         }
804
805         public class GenericMemberAccess : MemberAccess
806         {
807                 TypeArguments args;
808
809                 public GenericMemberAccess (Expression expr, string id, TypeArguments args, Location loc)
810                         : base (expr, id, args.Count, loc)
811                 {
812                         this.args = args;
813                 }
814
815                 private bool DoResolveBase (EmitContext ec)
816                 {
817                         ConstructedType cexpr = expr as ConstructedType;
818                         if (cexpr != null) {
819                                 TypeArguments new_args = new TypeArguments (loc);
820                                 new_args.Add (cexpr.TypeArguments);
821                                 new_args.Add (args);
822
823                                 args = new_args;
824                         }
825
826                         return true;
827                 }
828
829                 public override Expression DoResolve (EmitContext ec, Expression right_side,
830                                                       ResolveFlags flags)
831                 {
832                         if (!DoResolveBase (ec))
833                                 return null;
834
835                         Expression expr = base.DoResolve (ec, right_side, flags);
836                         if (expr == null)
837                                 return null;
838
839                         TypeExpr texpr = expr as TypeExpr;
840                         if (texpr != null) {
841                                 Type t = texpr.ResolveType (ec);
842                                 if (t == null)
843                                         return null;
844
845                                 ConstructedType ctype = new ConstructedType (t, args, loc);
846                                 return ctype.DoResolve (ec);
847                         }
848
849                         MethodGroupExpr mg = expr as MethodGroupExpr;
850                         if (mg == null) {
851                                 return expr;
852                                 Report.Error (-220, loc, "Member `{0}' has type arguments, but did " +
853                                               "not resolve as a method group.", Identifier);
854                                 return null;
855                         }
856
857                         if (args.Resolve (ec) == false)
858                                 return null;
859
860                         Type[] atypes = args.Arguments;
861
862                         ArrayList list = new ArrayList ();
863
864                         foreach (MethodBase method in mg.Methods) {
865                                 MethodInfo mi = method as MethodInfo;
866                                 if (mi == null)
867                                         continue;
868
869                                 Type[] gen_params = mi.GetGenericParameters ();
870                         
871                                 if (atypes.Length != gen_params.Length) {
872                                         Report.Error (-217, loc, "Generic method `{0}' takes {1} " +
873                                                       "type parameters, but specified {2}.", mi.Name,
874                                                       gen_params.Length, atypes.Length);
875                                         continue;
876                                 }
877
878                                 list.Add (mi.BindGenericParameters (args.Arguments));
879                         }
880
881                         MethodInfo[] methods = new MethodInfo [list.Count];
882                         list.CopyTo (methods, 0);
883
884                         MethodGroupExpr new_mg = new MethodGroupExpr (methods, mg.Location);
885                         new_mg.InstanceExpression = mg.InstanceExpression;
886                         new_mg.HasTypeArguments = true;
887                         return new_mg;
888                 }
889
890                 public override Expression ResolveAsTypeStep (EmitContext ec)
891                 {
892                         if (!DoResolveBase (ec))
893                                 return null;
894
895                         expr = base.ResolveAsTypeStep (ec);
896                         if (expr == null)
897                                 return null;
898
899                         Type t = ((TypeExpr) expr).ResolveType (ec);
900                         if (t == null)
901                                 return null;
902
903                         ConstructedType ctype = new ConstructedType (t, args, loc);
904                         return ctype.ResolveAsTypeStep (ec);
905                 }
906         }
907
908         public class DefaultValueExpression : Expression
909         {
910                 Expression expr;
911                 LocalTemporary temp_storage;
912
913                 public DefaultValueExpression (Expression expr, Location loc)
914                 {
915                         this.expr = expr;
916                         this.loc = loc;
917                 }
918
919                 public override Expression DoResolve (EmitContext ec)
920                 {
921                         type = ec.DeclSpace.ResolveType (expr, false, loc);
922                         if (type == null)
923                                 return null;
924
925                         if (type.IsGenericParameter || TypeManager.IsValueType (type))
926                                 temp_storage = new LocalTemporary (ec, type);
927
928                         eclass = ExprClass.Variable;
929                         return this;
930                 }
931
932                 public override void Emit (EmitContext ec)
933                 {
934                         if (temp_storage != null) {
935                                 temp_storage.AddressOf (ec, AddressOp.LoadStore);
936                                 ec.ig.Emit (OpCodes.Initobj, type);
937                                 temp_storage.Emit (ec);
938                         } else
939                                 ec.ig.Emit (OpCodes.Ldnull);
940                 }
941         }
942 }