- Added missing default
[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         public enum SpecialConstraint
19         {
20                 Constructor,
21                 ReferenceType,
22                 ValueType
23         }
24
25         //
26         // Tracks the constraints for a type parameter
27         //
28         public class Constraints : GenericConstraints {
29                 string name;
30                 ArrayList constraints;
31                 Location loc;
32                 
33                 //
34                 // name is the identifier, constraints is an arraylist of
35                 // Expressions (with types) or `true' for the constructor constraint.
36                 // 
37                 public Constraints (string name, ArrayList constraints,
38                                     Location loc)
39                 {
40                         this.name = name;
41                         this.constraints = constraints;
42                         this.loc = loc;
43                 }
44
45                 public string TypeParameter {
46                         get {
47                                 return name;
48                         }
49                 }
50
51                 bool has_ctor_constraint;
52                 bool has_reference_type;
53                 bool has_value_type;
54                 TypeExpr class_constraint;
55                 ArrayList iface_constraints;
56                 ArrayList type_param_constraints;
57                 int num_constraints, first_constraint;
58                 Type class_constraint_type;
59                 Type[] iface_constraint_types;
60
61                 public bool HasConstructorConstraint {
62                         get { return has_ctor_constraint; }
63                 }
64
65                 public bool Resolve (DeclSpace ds)
66                 {
67                         iface_constraints = new ArrayList ();
68                         type_param_constraints = new ArrayList ();
69
70                         foreach (object obj in constraints) {
71                                 if (has_ctor_constraint) {
72                                         Report.Error (401, loc,
73                                                       "The new() constraint must be last.");
74                                         return false;
75                                 }
76
77                                 if (obj is SpecialConstraint) {
78                                         SpecialConstraint sc = (SpecialConstraint) obj;
79
80                                         if (sc == SpecialConstraint.Constructor) {
81                                                 if (!has_value_type) {
82                                                         has_ctor_constraint = true;
83                                                         continue;
84                                                 }
85
86                                                 Report.Error (
87                                                         451, loc, "The new () constraint " +
88                                                         "cannot be used with the `struct' " +
89                                                         "constraint.");
90                                                 return false;
91                                         }
92
93                                         if ((num_constraints > 0) || has_reference_type ||
94                                             has_value_type) {
95                                                 Report.Error (449, loc,
96                                                               "The `class' or `struct' " +
97                                                               "constraint must be first");
98                                                 return false;
99                                         }
100
101                                         if (sc == SpecialConstraint.ReferenceType)
102                                                 has_reference_type = true;
103                                         else
104                                                 has_value_type = true;
105                                         continue;
106                                 }
107
108                                 TypeExpr expr = ds.ResolveTypeExpr ((Expression) obj, false, loc);
109                                 if (expr == null)
110                                         return false;
111
112                                 TypeParameterExpr texpr = expr as TypeParameterExpr;
113                                 if (texpr != null)
114                                         type_param_constraints.Add (expr);
115                                 else if (expr.IsInterface)
116                                         iface_constraints.Add (expr);
117                                 else if (class_constraint != null) {
118                                         Report.Error (406, loc,
119                                                       "`{0}': the class constraint for `{1}' " +
120                                                       "must come before any other constraints.",
121                                                       expr.Name, name);
122                                         return false;
123                                 } else if (has_reference_type || has_value_type) {
124                                         Report.Error (450, loc, "`{0}': cannot specify both " +
125                                                       "a constraint class and the `class' " +
126                                                       "or `struct' constraint.", expr.Name);
127                                         return false;
128                                 } else
129                                         class_constraint = expr;
130
131                                 num_constraints++;
132                         }
133
134                         return true;
135                 }
136
137                 bool CheckTypeParameterConstraints (TypeParameter tparam, Hashtable seen)
138                 {
139                         seen.Add (tparam, true);
140
141                         Constraints constraints = tparam.Constraints;
142                         if (constraints == null)
143                                 return true;
144
145                         if (constraints.IsValueType) {
146                                 Report.Error (456, loc, "Type parameter `{0}' has " +
147                                               "the `struct' constraint, so it cannot " +
148                                               "be used as a constraint for `{1}'",
149                                               tparam.Name, name);
150                                 return false;
151                         }
152
153                         if (constraints.type_param_constraints == null)
154                                 return true;
155
156                         foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
157                                 if (seen.Contains (expr.TypeParameter)) {
158                                         Report.Error (454, loc, "Circular constraint " +
159                                                       "dependency involving `{0}' and `{1}'",
160                                                       tparam.Name, expr.Name);
161                                         return false;
162                                 }
163
164                                 if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
165                                         return false;
166                         }
167
168                         return true;
169                 }
170
171                 public bool ResolveTypes (EmitContext ec)
172                 {
173                         foreach (TypeParameterExpr expr in type_param_constraints) {
174                                 Hashtable seen = new Hashtable ();
175                                 if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
176                                         return false;
177                         }
178
179                         ArrayList list = new ArrayList ();
180
181                         foreach (TypeExpr iface_constraint in iface_constraints) {
182                                 Type resolved = iface_constraint.ResolveType (ec);
183                                 if (resolved == null)
184                                         return false;
185
186                                 foreach (Type type in list) {
187                                         if (!type.Equals (resolved))
188                                                 continue;
189
190                                         Report.Error (405, loc,
191                                                       "Duplicate constraint `{0}' for type " +
192                                                       "parameter `{1}'.", resolved, name);
193                                         return false;
194                                 }
195
196                                 list.Add (resolved);
197                         }
198
199                         foreach (TypeParameterExpr expr in type_param_constraints) {
200                                 Type resolved = expr.ResolveType (ec);
201                                 if (resolved == null)
202                                         return false;
203
204                                 foreach (Type type in list) {
205                                         if (!type.Equals (resolved))
206                                                 continue;
207
208                                         Report.Error (405, loc,
209                                                       "Duplicate constraint `{0}' for type " +
210                                                       "parameter `{1}'.", resolved, name);
211                                         return false;
212                                 }
213
214                                 list.Add (resolved);
215                         }
216
217                         iface_constraint_types = new Type [list.Count];
218                         list.CopyTo (iface_constraint_types, 0);
219
220                         if (class_constraint != null) {
221                                 class_constraint_type = class_constraint.ResolveType (ec);
222                                 if (class_constraint_type == null)
223                                         return false;
224
225                                 if (class_constraint_type.IsSealed) {
226                                         Report.Error (701, loc,
227                                                       "`{0}' is not a valid bound.  Bounds " +
228                                                       "must be interfaces or non sealed " +
229                                                       "classes", class_constraint_type);
230                                         return false;
231                                 }
232
233                                 if ((class_constraint_type == TypeManager.array_type) ||
234                                     (class_constraint_type == TypeManager.delegate_type) ||
235                                     (class_constraint_type == TypeManager.enum_type) ||
236                                     (class_constraint_type == TypeManager.value_type) ||
237                                     (class_constraint_type == TypeManager.object_type)) {
238                                         Report.Error (702, loc,
239                                                       "Bound cannot be special class `{0}'",
240                                                       class_constraint_type);
241                                         return false;
242                                 }
243                         }
244
245                         if (has_reference_type)
246                                 class_constraint_type = TypeManager.object_type;
247                         else if (has_value_type)
248                                 class_constraint_type = TypeManager.value_type;
249
250                         return true;
251                 }
252
253                 public bool CheckDependencies (EmitContext ec)
254                 {
255                         foreach (TypeParameterExpr expr in type_param_constraints) {
256                                 if (!CheckDependencies (expr.TypeParameter, ec))
257                                         return false;
258                         }
259
260                         return true;
261                 }
262
263                 bool CheckDependencies (TypeParameter tparam, EmitContext ec)
264                 {
265                         Constraints constraints = tparam.Constraints;
266                         if (constraints == null)
267                                 return true;
268
269                         if (IsValueType && constraints.HasClassConstraint) {
270                                 Report.Error (455, loc, "Type parameter `{0}' inherits " +
271                                               "conflicting constraints `{1}' and `{2}'",
272                                               name, constraints.ClassConstraint,
273                                               "System.ValueType");
274                                 return false;
275                         }
276
277                         if (HasClassConstraint && constraints.HasClassConstraint) {
278                                 Type t1 = ClassConstraint;
279                                 TypeExpr e1 = class_constraint;
280                                 Type t2 = constraints.ClassConstraint;
281                                 TypeExpr e2 = constraints.class_constraint;
282
283                                 if (!Convert.ImplicitReferenceConversionExists (e1, t2) &&
284                                     !Convert.ImplicitReferenceConversionExists (e2, t1)) {
285                                         Report.Error (455, loc,
286                                                       "Type parameter `{0}' inherits " +
287                                                       "conflicting constraints `{1}' and `{2}'",
288                                                       name, t1, t2);
289                                         return false;
290                                 }
291                         }
292
293                         if (constraints.type_param_constraints == null)
294                                 return true;
295
296                         foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
297                                 if (!CheckDependencies (expr.TypeParameter, ec))
298                                         return false;
299                         }
300
301                         return true;
302                 }
303
304                 public void Define (GenericTypeParameterBuilder type)
305                 {
306                         if (has_ctor_constraint)
307                                 type.Mono_SetConstructorConstraint ();
308                         if (has_reference_type)
309                                 type.Mono_SetReferenceTypeConstraint ();
310                         else if (has_value_type)
311                                 type.Mono_SetValueTypeConstraint ();
312                 }
313
314                 public bool HasConstructor {
315                         get { return has_ctor_constraint; }
316                 }
317
318                 public bool IsReferenceType {
319                         get { return has_reference_type; }
320                 }
321
322                 public bool IsValueType {
323                         get { return has_value_type; }
324                 }
325
326                 public bool HasClassConstraint {
327                         get { return class_constraint_type != null; }
328                 }
329
330                 public Type ClassConstraint {
331                         get { return class_constraint_type; }
332                 }
333
334                 public Type[] InterfaceConstraints {
335                         get { return iface_constraint_types; }
336                 }
337
338                 internal bool IsSubclassOf (Type t)
339                 {
340                         if ((class_constraint_type != null) &&
341                             class_constraint_type.IsSubclassOf (t))
342                                 return true;
343
344                         if (iface_constraint_types == null)
345                                 return false;
346
347                         foreach (Type iface in iface_constraint_types) {
348                                 if (TypeManager.IsSubclassOf (iface, t))
349                                         return true;
350                         }
351
352                         return false;
353                 }
354
355                 public bool CheckInterfaceMethod (EmitContext ec, GenericConstraints gc)
356                 {
357                         if (!ResolveTypes (ec))
358                                 return false;
359
360                         if (gc.HasConstructor != HasConstructor)
361                                 return false;
362                         if (gc.IsReferenceType != IsReferenceType)
363                                 return false;
364                         if (gc.IsValueType != IsValueType)
365                                 return false;
366                         if (gc.HasClassConstraint != HasClassConstraint)
367                                 return false;
368
369                         if (HasClassConstraint && !gc.ClassConstraint.Equals (ClassConstraint))
370                                 return false;
371
372                         int gc_icount = gc.InterfaceConstraints != null ?
373                                 gc.InterfaceConstraints.Length : 0;
374                         int icount = InterfaceConstraints != null ?
375                                 InterfaceConstraints.Length : 0;
376
377                         if (gc_icount != icount)
378                                 return false;
379
380                         foreach (Type iface in gc.InterfaceConstraints) {
381                                 bool ok = false;
382                                 foreach (Type check in InterfaceConstraints) {
383                                         if (iface.Equals (check)) {
384                                                 ok = true;
385                                                 break;
386                                         }
387                                 }
388
389                                 if (!ok)
390                                         return false;
391                         }
392
393                         return true;
394                 }
395         }
396
397         //
398         // This type represents a generic type parameter
399         //
400         public class TypeParameter : IMemberContainer {
401                 string name;
402                 Constraints constraints;
403                 Location loc;
404                 GenericTypeParameterBuilder type;
405
406                 public TypeParameter (string name, Constraints constraints, Location loc)
407                 {
408                         this.name = name;
409                         this.constraints = constraints;
410                         this.loc = loc;
411                 }
412
413                 public string Name {
414                         get {
415                                 return name;
416                         }
417                 }
418
419                 public Location Location {
420                         get {
421                                 return loc;
422                         }
423                 }
424
425                 public Constraints Constraints {
426                         get {
427                                 return constraints;
428                         }
429                 }
430
431                 public bool HasConstructorConstraint {
432                         get {
433                                 if (constraints != null)
434                                         return constraints.HasConstructorConstraint;
435
436                                 return false;
437                         }
438                 }
439
440                 public Type Type {
441                         get {
442                                 return type;
443                         }
444                 }
445
446                 public bool Resolve (DeclSpace ds)
447                 {
448                         if (constraints != null)
449                                 return constraints.Resolve (ds);
450
451                         return true;
452                 }
453
454                 public void Define (GenericTypeParameterBuilder type)
455                 {
456                         this.type = type;
457                         Type[] ifaces = null;
458                         if (constraints != null)
459                                 constraints.Define (type);
460                         TypeManager.AddTypeParameter (type, this);
461                 }
462
463                 public bool DefineType (EmitContext ec)
464                 {
465                         return DefineType (ec, null, null, false);
466                 }
467
468                 public bool DefineType (EmitContext ec, MethodBuilder builder,
469                                         MethodInfo implementing, bool is_override)
470                 {
471                         GenericConstraints gc;
472
473                         if (implementing != null) {
474                                 if (is_override && (constraints != null)) {
475                                         Report.Error (
476                                                 460, loc, "Constraints for override and " +
477                                                 "explicit interface implementation methods " +
478                                                 "are inherited from the base method so they " +
479                                                 "cannot be specified directly");
480                                         return false;
481                                 }
482
483                                 MethodBase mb = implementing;
484                                 if (mb.Mono_IsInflatedMethod)
485                                         mb = mb.GetGenericMethodDefinition ();
486
487                                 int pos = type.GenericParameterPosition;
488                                 ParameterData pd = Invocation.GetParameterData (mb);
489                                 gc = pd.GenericConstraints (pos);
490                                 Type mparam = mb.GetGenericArguments () [pos];
491
492                                 if (((constraints != null) && (gc == null)) ||
493                                     ((constraints == null) && (gc != null)) ||
494                                     ((constraints != null) &&
495                                      !constraints.CheckInterfaceMethod (ec, gc))) {
496                                         Report.SymbolRelatedToPreviousError (implementing);
497
498                                         Report.Error (
499                                                 425, loc, "The constraints for type " +
500                                                 "parameter `{0}' of method `{1}' must match " +
501                                                 "the constraints for type parameter `{2}' " +
502                                                 "of interface method `{3}'.  Consider using " +
503                                                 "an explicit interface implementation instead",
504                                                 Name, TypeManager.CSharpSignature (builder),
505                                                 mparam, TypeManager.CSharpSignature (mb));
506                                         return false;
507                                 }
508                         } else {
509                                 if (constraints != null) {
510                                         if (!constraints.ResolveTypes (ec))
511                                                 return false;
512                                 }
513
514                                 gc = (GenericConstraints) constraints;
515                         }
516
517                         if (gc == null)
518                                 return true;
519
520                         if (gc.HasClassConstraint)
521                                 type.SetBaseTypeConstraint (gc.ClassConstraint);
522
523                         type.SetInterfaceConstraints (gc.InterfaceConstraints);
524                         TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
525
526                         return true;
527                 }
528
529                 public bool CheckDependencies (EmitContext ec)
530                 {
531                         if (constraints != null)
532                                 return constraints.CheckDependencies (ec);
533
534                         return true;
535                 }
536
537                 //
538                 // IMemberContainer
539                 //
540
541                 IMemberContainer IMemberContainer.ParentContainer {
542                         get { return null; }
543                 }
544
545                 bool IMemberContainer.IsInterface {
546                         get { return true; }
547                 }
548
549                 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
550                 {
551                         return FindMembers (mt, bf, null, null);
552                 }
553
554                 MemberCache IMemberContainer.MemberCache {
555                         get { return null; }
556                 }
557
558                 public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
559                                                MemberFilter filter, object criteria)
560                 {
561                         if (constraints == null)
562                                 return MemberList.Empty;
563
564                         ArrayList members = new ArrayList ();
565
566                         GenericConstraints gc = (GenericConstraints) constraints;
567
568                         if (gc.HasClassConstraint) {
569                                 MemberList list = TypeManager.FindMembers (
570                                         gc.ClassConstraint, mt, bf, filter, criteria);
571
572                                 members.AddRange (list);
573                         }
574
575                         foreach (Type t in gc.InterfaceConstraints) {
576                                 MemberList list = TypeManager.FindMembers (
577                                         t, mt, bf, filter, criteria);
578
579                                 members.AddRange (list);
580                         }
581
582                         return new MemberList (members);
583                 }
584
585                 public bool IsSubclassOf (Type t)
586                 {
587                         if (type.Equals (t))
588                                 return true;
589
590                         if (constraints != null)
591                                 return constraints.IsSubclassOf (t);
592
593                         return false;
594                 }
595
596                 public override string ToString ()
597                 {
598                         return "TypeParameter[" + name + "]";
599                 }
600         }
601
602         //
603         // This type represents a generic type parameter reference.
604         //
605         // These expressions are born in a fully resolved state.
606         //
607         public class TypeParameterExpr : TypeExpr {
608                 TypeParameter type_parameter;
609
610                 public override string Name {
611                         get {
612                                 return type_parameter.Name;
613                         }
614                 }
615
616                 public TypeParameter TypeParameter {
617                         get {
618                                 return type_parameter;
619                         }
620                 }
621                 
622                 public TypeParameterExpr (TypeParameter type_parameter, Location loc)
623                 {
624                         this.type_parameter = type_parameter;
625                         this.loc = loc;
626                 }
627
628                 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
629                 {
630                         type = type_parameter.Type;
631
632                         return this;
633                 }
634
635                 public override bool IsInterface {
636                         get { return false; }
637                 }
638
639                 public void Error_CannotUseAsUnmanagedType (Location loc)
640                 {
641                         Report.Error (-203, loc, "Can not use type parameter as unamanged type");
642                 }
643         }
644
645         public class TypeArguments {
646                 public readonly Location Location;
647                 ArrayList args;
648                 Type[] atypes;
649                 int dimension;
650                 bool has_type_args;
651                 bool created;
652                 
653                 public TypeArguments (Location loc)
654                 {
655                         args = new ArrayList ();
656                         this.Location = loc;
657                 }
658
659                 public TypeArguments (int dimension, Location loc)
660                 {
661                         this.dimension = dimension;
662                         this.Location = loc;
663                 }
664
665                 public void Add (Expression type)
666                 {
667                         if (created)
668                                 throw new InvalidOperationException ();
669
670                         args.Add (type);
671                 }
672
673                 public void Add (TypeArguments new_args)
674                 {
675                         if (created)
676                                 throw new InvalidOperationException ();
677
678                         args.AddRange (new_args.args);
679                 }
680
681                 public string[] GetDeclarations ()
682                 {
683                         string[] ret = new string [args.Count];
684                         for (int i = 0; i < args.Count; i++) {
685                                 SimpleName sn = args [i] as SimpleName;
686                                 if (sn != null) {
687                                         ret [i] = sn.Name;
688                                         continue;
689                                 }
690
691                                 Report.Error (81, Location, "Type parameter declaration " +
692                                               "must be an identifier not a type");
693                                 return null;
694                         }
695                         return ret;
696                 }
697
698                 public Type[] Arguments {
699                         get {
700                                 return atypes;
701                         }
702                 }
703
704                 public bool HasTypeArguments {
705                         get {
706                                 return has_type_args;
707                         }
708                 }
709
710                 public int Count {
711                         get {
712                                 if (dimension > 0)
713                                         return dimension;
714                                 else
715                                         return args.Count;
716                         }
717                 }
718
719                 public bool IsUnbound {
720                         get {
721                                 return dimension > 0;
722                         }
723                 }
724
725                 public override string ToString ()
726                 {
727                         StringBuilder s = new StringBuilder ();
728
729                         int count = Count;
730                         for (int i = 0; i < count; i++){
731                                 //
732                                 // FIXME: Use TypeManager.CSharpname once we have the type
733                                 //
734                                 if (args != null)
735                                         s.Append (args [i].ToString ());
736                                 if (i+1 < count)
737                                         s.Append (",");
738                         }
739                         return s.ToString ();
740                 }
741
742                 public bool Resolve (EmitContext ec)
743                 {
744                         DeclSpace ds = ec.DeclSpace;
745                         int count = args.Count;
746                         bool ok = true;
747
748                         atypes = new Type [count];
749
750                         for (int i = 0; i < count; i++){
751                                 TypeExpr te = ds.ResolveTypeExpr (
752                                         (Expression) args [i], false, Location);
753                                 if (te == null) {
754                                         ok = false;
755                                         continue;
756                                 }
757                                 if (te is TypeParameterExpr)
758                                         has_type_args = true;
759                                 atypes [i] = te.ResolveType (ec);
760
761                                 if (atypes [i] == null) {
762                                         Report.Error (246, Location, "Cannot find type `{0}'",
763                                                       te.Name);
764                                         ok = false;
765                                 }
766                         }
767                         return ok;
768                 }
769         }
770         
771         public class ConstructedType : TypeExpr {
772                 string name, full_name;
773                 TypeArguments args;
774                 Type[] gen_params, atypes;
775                 Type gt;
776                 
777                 public ConstructedType (string name, TypeArguments args, Location l)
778                 {
779                         loc = l;
780                         this.name = MemberName.MakeName (name, args.Count);
781                         this.args = args;
782
783                         eclass = ExprClass.Type;
784                         full_name = name + "<" + args.ToString () + ">";
785                 }
786
787                 public ConstructedType (string name, TypeParameter[] type_params, Location l)
788                         : this (type_params, l)
789                 {
790                         loc = l;
791
792                         this.name = name;
793                         full_name = name + "<" + args.ToString () + ">";
794                 }
795
796                 protected ConstructedType (TypeArguments args, Location l)
797                 {
798                         loc = l;
799                         this.args = args;
800
801                         eclass = ExprClass.Type;
802                 }
803
804                 protected ConstructedType (TypeParameter[] type_params, Location l)
805                 {
806                         loc = l;
807
808                         args = new TypeArguments (l);
809                         foreach (TypeParameter type_param in type_params)
810                                 args.Add (new TypeParameterExpr (type_param, l));
811
812                         eclass = ExprClass.Type;
813                 }
814
815                 public ConstructedType (Type t, TypeParameter[] type_params, Location l)
816                         : this (type_params, l)
817                 {
818                         gt = t.GetGenericTypeDefinition ();
819
820                         this.name = gt.FullName;
821                         full_name = gt.FullName + "<" + args.ToString () + ">";
822                 }
823
824                 public ConstructedType (Type t, TypeArguments args, Location l)
825                         : this (args, l)
826                 {
827                         gt = t.GetGenericTypeDefinition ();
828
829                         this.name = gt.FullName;
830                         full_name = gt.FullName + "<" + args.ToString () + ">";
831                 }
832
833                 public TypeArguments TypeArguments {
834                         get { return args; }
835                 }
836
837                 protected string DeclarationName {
838                         get {
839                                 StringBuilder sb = new StringBuilder ();
840                                 sb.Append (gt.FullName);
841                                 sb.Append ("<");
842                                 for (int i = 0; i < gen_params.Length; i++) {
843                                         if (i > 0)
844                                                 sb.Append (",");
845                                         sb.Append (gen_params [i]);
846                                 }
847                                 sb.Append (">");
848                                 return sb.ToString ();
849                         }
850                 }
851
852                 protected bool CheckConstraint (EmitContext ec, Type ptype, Expression expr,
853                                                 Type ctype)
854                 {
855                         if (TypeManager.HasGenericArguments (ctype)) {
856                                 Type[] types = TypeManager.GetTypeArguments (ctype);
857
858                                 TypeArguments new_args = new TypeArguments (loc);
859
860                                 for (int i = 0; i < types.Length; i++) {
861                                         Type t = types [i];
862
863                                         if (t.IsGenericParameter) {
864                                                 int pos = t.GenericParameterPosition;
865                                                 t = args.Arguments [pos];
866                                         }
867                                         new_args.Add (new TypeExpression (t, loc));
868                                 }
869
870                                 ctype = new ConstructedType (ctype, new_args, loc).ResolveType (ec);
871                                 if (ctype == null)
872                                         return false;
873                         }
874
875                         return Convert.ImplicitStandardConversionExists (expr, ctype);
876                 }
877
878                 protected bool CheckConstraints (EmitContext ec, int index)
879                 {
880                         Type atype = atypes [index];
881                         Type ptype = gen_params [index];
882
883                         if (atype == ptype)
884                                 return true;
885
886                         Expression aexpr = new EmptyExpression (atype);
887
888                         Type parent = ptype.BaseType;
889
890                         //
891                         // First, check the `class' and `struct' constraints.
892                         //
893                         if (parent == TypeManager.object_type) {
894                                 if (!atype.IsClass) {
895                                         Report.Error (452, loc, "The type `{0}' must be " +
896                                                       "a reference type in order to use it " +
897                                                       "as type parameter `{1}' in the " +
898                                                       "generic type or method `{2}'.",
899                                                       atype, ptype, DeclarationName);
900                                         return false;
901                                 }
902                         } else if (parent == TypeManager.value_type) {
903                                 if (!atype.IsValueType) {
904                                         Report.Error (453, loc, "The type `{0}' must be " +
905                                                       "a value type in order to use it " +
906                                                       "as type parameter `{1}' in the " +
907                                                       "generic type or method `{2}'.",
908                                                       atype, ptype, DeclarationName);
909                                         return false;
910                                 }
911                         }
912
913                         //
914                         // The class constraint comes next.
915                         //
916                         if ((parent != null) && (parent != TypeManager.object_type)) {
917                                 if (!CheckConstraint (ec, ptype, aexpr, parent)) {
918                                         Report.Error (309, loc, "The type `{0}' must be " +
919                                                       "convertible to `{1}' in order to " +
920                                                       "use it as parameter `{2}' in the " +
921                                                       "generic type or method `{3}'",
922                                                       atype, parent, ptype, DeclarationName);
923                                         return false;
924                                 }
925                         }
926
927                         //
928                         // Now, check the interface constraints.
929                         //
930                         foreach (Type it in TypeManager.GetInterfaces (ptype)) {
931                                 Type itype;
932                                 if (it.IsGenericParameter)
933                                         itype = atypes [it.GenericParameterPosition];
934                                 else
935                                         itype = it;
936
937                                 if (!CheckConstraint (ec, ptype, aexpr, itype)) {
938                                         Report.Error (309, loc, "The type `{0}' must be " +
939                                                       "convertible to `{1}' in order to " +
940                                                       "use it as parameter `{2}' in the " +
941                                                       "generic type or method `{3}'",
942                                                       atype, itype, ptype, DeclarationName);
943                                         return false;
944                                 }
945                         }
946
947                         //
948                         // Finally, check the constructor constraint.
949                         //
950
951                         if (!TypeManager.HasConstructorConstraint (ptype))
952                                 return true;
953
954                         MethodGroupExpr mg = Expression.MemberLookup (
955                                 ec, atype, ".ctor", MemberTypes.Constructor,
956                                 BindingFlags.Public | BindingFlags.Instance |
957                                 BindingFlags.DeclaredOnly, loc)
958                                 as MethodGroupExpr;
959
960                         if (atype.IsAbstract || (mg == null) || !mg.IsInstance) {
961                                 Report.Error (310, loc, "The type `{0}' must have a public " +
962                                               "parameterless constructor in order to use it " +
963                                               "as parameter `{1}' in the generic type or " +
964                                               "method `{2}'", atype, ptype, DeclarationName);
965                                 return false;
966                         }
967
968                         return true;
969                 }
970
971                 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
972                 {
973                         if (gt != null)
974                                 return this;
975
976                         //
977                         // First, resolve the generic type.
978                         //
979                         DeclSpace ds;
980                         Type nested = ec.DeclSpace.FindNestedType (loc, name, out ds);
981                         if (nested != null) {
982                                 gt = nested.GetGenericTypeDefinition ();
983
984                                 TypeArguments new_args = new TypeArguments (loc);
985                                 foreach (TypeParameter param in ds.TypeParameters)
986                                         new_args.Add (new TypeParameterExpr (param, loc));
987                                 new_args.Add (args);
988
989                                 args = new_args;
990                                 return this;
991                         }
992
993                         Type t;
994                         int num_args;
995
996                         SimpleName sn = new SimpleName (name, loc);
997                         TypeExpr resolved = sn.ResolveAsTypeTerminal (ec);
998                         if ((resolved == null) || (resolved.Type == null)) {
999                                 Report.Error (246, loc,
1000                                               "The type or namespace name `{0}<...>' "+
1001                                               "could not be found", Basename);
1002                                 return null;
1003                         }
1004
1005                         t = resolved.Type;
1006                         if (t == null) {
1007                                 Report.Error (246, loc, "Cannot find type `{0}'<...>",
1008                                               Basename);
1009                                 return null;
1010                         }
1011
1012                         num_args = TypeManager.GetNumberOfTypeArguments (t);
1013                         if (num_args == 0) {
1014                                 Report.Error (308, loc,
1015                                               "The non-generic type `{0}' cannot " +
1016                                               "be used with type arguments.",
1017                                               TypeManager.CSharpName (t));
1018                                 return null;
1019                         }
1020
1021                         gt = t.GetGenericTypeDefinition ();
1022                         return this;
1023                 }
1024
1025                 public override Type ResolveType (EmitContext ec)
1026                 {
1027                         if (type != null)
1028                                 return type;
1029                         if (DoResolveAsTypeStep (ec) == null)
1030                                 return null;
1031
1032                         //
1033                         // Resolve the arguments.
1034                         //
1035                         if (args.Resolve (ec) == false)
1036                                 return null;
1037
1038                         gen_params = gt.GetGenericArguments ();
1039                         atypes = args.Arguments;
1040
1041                         if (atypes.Length != gen_params.Length) {
1042                                 Report.Error (305, loc,
1043                                               "Using the generic type `{0}' " +
1044                                               "requires {1} type arguments",
1045                                               TypeManager.GetFullName (gt),
1046                                               gen_params.Length);
1047                                 return null;
1048                         }
1049
1050                         for (int i = 0; i < gen_params.Length; i++) {
1051                                 if (!CheckConstraints (ec, i))
1052                                         return null;
1053                         }
1054
1055                         //
1056                         // Now bind the parameters.
1057                         //
1058                         type = gt.BindGenericParameters (atypes);
1059                         return type;
1060                 }
1061
1062                 public Expression GetSimpleName (EmitContext ec)
1063                 {
1064                         return new SimpleName (Basename, args, loc);
1065                 }
1066
1067                 public override bool CheckAccessLevel (DeclSpace ds)
1068                 {
1069                         return ds.CheckAccessLevel (gt);
1070                 }
1071
1072                 public override bool AsAccessible (DeclSpace ds, int flags)
1073                 {
1074                         return ds.AsAccessible (gt, flags);
1075                 }
1076
1077                 public override bool IsClass {
1078                         get { return gt.IsClass; }
1079                 }
1080
1081                 public override bool IsValueType {
1082                         get { return gt.IsValueType; }
1083                 }
1084
1085                 public override bool IsInterface {
1086                         get { return gt.IsInterface; }
1087                 }
1088
1089                 public override bool IsSealed {
1090                         get { return gt.IsSealed; }
1091                 }
1092
1093                 public override bool IsAttribute {
1094                         get { return false; }
1095                 }
1096
1097                 public override bool Equals (object obj)
1098                 {
1099                         ConstructedType cobj = obj as ConstructedType;
1100                         if (cobj == null)
1101                                 return false;
1102
1103                         if ((type == null) || (cobj.type == null))
1104                                 return false;
1105
1106                         return type == cobj.type;
1107                 }
1108
1109                 public string Basename {
1110                         get {
1111                                 int pos = name.LastIndexOf ('`');
1112                                 if (pos >= 0)
1113                                         return name.Substring (0, pos);
1114                                 else
1115                                         return name;
1116                         }
1117                 }
1118
1119                 public override string Name {
1120                         get {
1121                                 return full_name;
1122                         }
1123                 }
1124         }
1125
1126         public class GenericMethod : DeclSpace
1127         {
1128                 public GenericMethod (NamespaceEntry ns, TypeContainer parent,
1129                                       MemberName name, Location l)
1130                         : base (ns, parent, name, null, l)
1131                 { }
1132
1133                 public override TypeBuilder DefineType ()
1134                 {
1135                         throw new Exception ();
1136                 }
1137
1138                 public override bool Define ()
1139                 {
1140                         for (int i = 0; i < TypeParameters.Length; i++)
1141                                 if (!TypeParameters [i].Resolve (Parent))
1142                                         return false;
1143
1144                         return true;
1145                 }
1146
1147                 public bool Define (MethodBuilder mb)
1148                 {
1149                         if (!Define ())
1150                                 return false;
1151
1152                         GenericTypeParameterBuilder[] gen_params;
1153                         string[] names = MemberName.TypeArguments.GetDeclarations ();
1154                         gen_params = mb.DefineGenericParameters (names);
1155                         for (int i = 0; i < TypeParameters.Length; i++)
1156                                 TypeParameters [i].Define (gen_params [i]);
1157
1158                         return true;
1159                 }
1160
1161                 public bool DefineType (EmitContext ec, MethodBuilder mb,
1162                                         MethodInfo implementing, bool is_override)
1163                 {
1164                         for (int i = 0; i < TypeParameters.Length; i++)
1165                                 if (!TypeParameters [i].DefineType (
1166                                             ec, mb, implementing, is_override))
1167                                         return false;
1168
1169                         return true;
1170                 }
1171
1172                 public override bool DefineMembers (TypeContainer parent)
1173                 {
1174                         return true;
1175                 }
1176
1177                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1178                                                         MemberFilter filter, object criteria)
1179                 {
1180                         throw new Exception ();
1181                 }               
1182
1183                 public override MemberCache MemberCache {
1184                         get {
1185                                 throw new Exception ();
1186                         }
1187                 }
1188
1189                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
1190                 {
1191                         // FIXME
1192                 }
1193
1194                 protected override void VerifyObsoleteAttribute()
1195                 {
1196                         // FIXME
1197                 }
1198
1199                 public override AttributeTargets AttributeTargets {
1200                         get {
1201                                 return AttributeTargets.Method | AttributeTargets.ReturnValue;
1202                         }
1203                 }
1204         }
1205
1206         public class DefaultValueExpression : Expression
1207         {
1208                 Expression expr;
1209                 LocalTemporary temp_storage;
1210
1211                 public DefaultValueExpression (Expression expr, Location loc)
1212                 {
1213                         this.expr = expr;
1214                         this.loc = loc;
1215                 }
1216
1217                 public override Expression DoResolve (EmitContext ec)
1218                 {
1219                         type = ec.DeclSpace.ResolveType (expr, false, loc);
1220                         if (type == null)
1221                                 return null;
1222
1223                         if (type.IsGenericParameter || TypeManager.IsValueType (type))
1224                                 temp_storage = new LocalTemporary (ec, type);
1225
1226                         eclass = ExprClass.Variable;
1227                         return this;
1228                 }
1229
1230                 public override void Emit (EmitContext ec)
1231                 {
1232                         if (temp_storage != null) {
1233                                 temp_storage.AddressOf (ec, AddressOp.LoadStore);
1234                                 ec.ig.Emit (OpCodes.Initobj, type);
1235                                 temp_storage.Emit (ec);
1236                         } else
1237                                 ec.ig.Emit (OpCodes.Ldnull);
1238                 }
1239         }
1240 }