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