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