2009-02-18 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / generic.cs
1 //
2 // generic.cs: Generics support
3 //
4 // Authors: Martin Baulig (martin@ximian.com)
5 //          Miguel de Icaza (miguel@ximian.com)
6 //          Marek Safar (marek.safar@gmail.com)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
12 //
13 using System;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Globalization;
17 using System.Collections;
18 using System.Text;
19 using System.Text.RegularExpressions;
20         
21 namespace Mono.CSharp {
22
23         /// <summary>
24         ///   Abstract base class for type parameter constraints.
25         ///   The type parameter can come from a generic type definition or from reflection.
26         /// </summary>
27         public abstract class GenericConstraints {
28                 public abstract string TypeParameter {
29                         get;
30                 }
31
32                 public abstract GenericParameterAttributes Attributes {
33                         get;
34                 }
35
36                 public bool HasConstructorConstraint {
37                         get { return (Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0; }
38                 }
39
40                 public bool HasReferenceTypeConstraint {
41                         get { return (Attributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0; }
42                 }
43
44                 public bool HasValueTypeConstraint {
45                         get { return (Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; }
46                 }
47
48                 public virtual bool HasClassConstraint {
49                         get { return ClassConstraint != null; }
50                 }
51
52                 public abstract Type ClassConstraint {
53                         get;
54                 }
55
56                 public abstract Type[] InterfaceConstraints {
57                         get;
58                 }
59
60                 public abstract Type EffectiveBaseClass {
61                         get;
62                 }
63
64                 // <summary>
65                 //   Returns whether the type parameter is "known to be a reference type".
66                 // </summary>
67                 public virtual bool IsReferenceType {
68                         get {
69                                 if (HasReferenceTypeConstraint)
70                                         return true;
71                                 if (HasValueTypeConstraint)
72                                         return false;
73
74                                 if (ClassConstraint != null) {
75                                         if (ClassConstraint.IsValueType)
76                                                 return false;
77
78                                         if (ClassConstraint != TypeManager.object_type)
79                                                 return true;
80                                 }
81
82                                 foreach (Type t in InterfaceConstraints) {
83                                         if (!t.IsGenericParameter)
84                                                 continue;
85
86                                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t);
87                                         if ((gc != null) && gc.IsReferenceType)
88                                                 return true;
89                                 }
90
91                                 return false;
92                         }
93                 }
94
95                 // <summary>
96                 //   Returns whether the type parameter is "known to be a value type".
97                 // </summary>
98                 public virtual bool IsValueType {
99                         get {
100                                 if (HasValueTypeConstraint)
101                                         return true;
102                                 if (HasReferenceTypeConstraint)
103                                         return false;
104
105                                 if (ClassConstraint != null) {
106                                         if (!ClassConstraint.IsValueType)
107                                                 return false;
108
109                                         if (ClassConstraint != TypeManager.value_type)
110                                                 return true;
111                                 }
112
113                                 foreach (Type t in InterfaceConstraints) {
114                                         if (!t.IsGenericParameter)
115                                                 continue;
116
117                                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t);
118                                         if ((gc != null) && gc.IsValueType)
119                                                 return true;
120                                 }
121
122                                 return false;
123                         }
124                 }
125         }
126
127         public enum Variance
128         {
129                 None,
130                 Covariant,
131                 Contravariant
132         }
133
134         public enum SpecialConstraint
135         {
136                 Constructor,
137                 ReferenceType,
138                 ValueType
139         }
140
141         /// <summary>
142         ///   Tracks the constraints for a type parameter from a generic type definition.
143         /// </summary>
144         public class Constraints : GenericConstraints {
145                 string name;
146                 ArrayList constraints;
147                 Location loc;
148                 
149                 //
150                 // name is the identifier, constraints is an arraylist of
151                 // Expressions (with types) or `true' for the constructor constraint.
152                 // 
153                 public Constraints (string name, ArrayList constraints,
154                                     Location loc)
155                 {
156                         this.name = name;
157                         this.constraints = constraints;
158                         this.loc = loc;
159                 }
160
161                 public override string TypeParameter {
162                         get {
163                                 return name;
164                         }
165                 }
166
167                 public Constraints Clone ()
168                 {
169                         return new Constraints (name, constraints, loc);
170                 }
171
172                 GenericParameterAttributes attrs;
173                 TypeExpr class_constraint;
174                 ArrayList iface_constraints;
175                 ArrayList type_param_constraints;
176                 int num_constraints;
177                 Type class_constraint_type;
178                 Type[] iface_constraint_types;
179                 Type effective_base_type;
180                 bool resolved;
181                 bool resolved_types;
182
183                 /// <summary>
184                 ///   Resolve the constraints - but only resolve things into Expression's, not
185                 ///   into actual types.
186                 /// </summary>
187                 public bool Resolve (IResolveContext ec)
188                 {
189                         if (resolved)
190                                 return true;
191
192                         iface_constraints = new ArrayList (2);  // TODO: Too expensive allocation
193                         type_param_constraints = new ArrayList ();
194
195                         foreach (object obj in constraints) {
196                                 if (HasConstructorConstraint) {
197                                         Report.Error (401, loc,
198                                                       "The new() constraint must be the last constraint specified");
199                                         return false;
200                                 }
201
202                                 if (obj is SpecialConstraint) {
203                                         SpecialConstraint sc = (SpecialConstraint) obj;
204
205                                         if (sc == SpecialConstraint.Constructor) {
206                                                 if (!HasValueTypeConstraint) {
207                                                         attrs |= GenericParameterAttributes.DefaultConstructorConstraint;
208                                                         continue;
209                                                 }
210
211                                                 Report.Error (451, loc, "The `new()' constraint " +
212                                                         "cannot be used with the `struct' constraint");
213                                                 return false;
214                                         }
215
216                                         if ((num_constraints > 0) || HasReferenceTypeConstraint || HasValueTypeConstraint) {
217                                                 Report.Error (449, loc, "The `class' or `struct' " +
218                                                               "constraint must be the first constraint specified");
219                                                 return false;
220                                         }
221
222                                         if (sc == SpecialConstraint.ReferenceType)
223                                                 attrs |= GenericParameterAttributes.ReferenceTypeConstraint;
224                                         else
225                                                 attrs |= GenericParameterAttributes.NotNullableValueTypeConstraint;
226                                         continue;
227                                 }
228
229                                 int errors = Report.Errors;
230                                 FullNamedExpression fn = ((Expression) obj).ResolveAsTypeStep (ec, false);
231
232                                 if (fn == null) {
233                                         if (errors != Report.Errors)
234                                                 return false;
235
236                                         NamespaceEntry.Error_NamespaceNotFound (loc, ((Expression)obj).GetSignatureForError ());
237                                         return false;
238                                 }
239
240                                 TypeExpr expr;
241                                 GenericTypeExpr cexpr = fn as GenericTypeExpr;
242                                 if (cexpr != null) {
243                                         expr = cexpr.ResolveAsBaseTerminal (ec, false);
244                                 } else
245                                         expr = ((Expression) obj).ResolveAsTypeTerminal (ec, false);
246
247                                 if ((expr == null) || (expr.Type == null))
248                                         return false;
249
250                                 if (!ec.GenericDeclContainer.IsAccessibleAs (fn.Type)) {
251                                         Report.SymbolRelatedToPreviousError (fn.Type);
252                                         Report.Error (703, loc,
253                                                 "Inconsistent accessibility: constraint type `{0}' is less accessible than `{1}'",
254                                                 fn.GetSignatureForError (), ec.GenericDeclContainer.GetSignatureForError ());
255                                         return false;
256                                 }
257
258                                 TypeParameterExpr texpr = expr as TypeParameterExpr;
259                                 if (texpr != null)
260                                         type_param_constraints.Add (expr);
261                                 else if (expr.IsInterface)
262                                         iface_constraints.Add (expr);
263                                 else if (class_constraint != null || iface_constraints.Count != 0) {
264                                         Report.Error (406, loc,
265                                                 "The class type constraint `{0}' must be listed before any other constraints. Consider moving type constraint to the beginning of the constraint list",
266                                                 expr.GetSignatureForError ());
267                                         return false;
268                                 } else if (HasReferenceTypeConstraint || HasValueTypeConstraint) {
269                                         Report.Error (450, loc, "`{0}': cannot specify both " +
270                                                       "a constraint class and the `class' " +
271                                                       "or `struct' constraint", expr.GetSignatureForError ());
272                                         return false;
273                                 } else
274                                         class_constraint = expr;
275
276                                 num_constraints++;
277                         }
278
279                         ArrayList list = new ArrayList ();
280                         foreach (TypeExpr iface_constraint in iface_constraints) {
281                                 foreach (Type type in list) {
282                                         if (!type.Equals (iface_constraint.Type))
283                                                 continue;
284
285                                         Report.Error (405, loc,
286                                                       "Duplicate constraint `{0}' for type " +
287                                                       "parameter `{1}'.", iface_constraint.GetSignatureForError (),
288                                                       name);
289                                         return false;
290                                 }
291
292                                 list.Add (iface_constraint.Type);
293                         }
294
295                         foreach (TypeParameterExpr expr in type_param_constraints) {
296                                 foreach (Type type in list) {
297                                         if (!type.Equals (expr.Type))
298                                                 continue;
299
300                                         Report.Error (405, loc,
301                                                       "Duplicate constraint `{0}' for type " +
302                                                       "parameter `{1}'.", expr.GetSignatureForError (), name);
303                                         return false;
304                                 }
305
306                                 list.Add (expr.Type);
307                         }
308
309                         iface_constraint_types = new Type [list.Count];
310                         list.CopyTo (iface_constraint_types, 0);
311
312                         if (class_constraint != null) {
313                                 class_constraint_type = class_constraint.Type;
314                                 if (class_constraint_type == null)
315                                         return false;
316
317                                 if (class_constraint_type.IsSealed) {
318                                         if (class_constraint_type.IsAbstract)
319                                         {
320                                                 Report.Error (717, loc, "`{0}' is not a valid constraint. Static classes cannot be used as constraints",
321                                                         TypeManager.CSharpName (class_constraint_type));
322                                         }
323                                         else
324                                         {
325                                                 Report.Error (701, loc, "`{0}' is not a valid constraint. A constraint must be an interface, " +
326                                                         "a non-sealed class or a type parameter", TypeManager.CSharpName(class_constraint_type));
327                                         }
328                                         return false;
329                                 }
330
331                                 if ((class_constraint_type == TypeManager.array_type) ||
332                                     (class_constraint_type == TypeManager.delegate_type) ||
333                                     (class_constraint_type == TypeManager.enum_type) ||
334                                     (class_constraint_type == TypeManager.value_type) ||
335                                     (class_constraint_type == TypeManager.object_type) ||
336                                         class_constraint_type == TypeManager.multicast_delegate_type) {
337                                         Report.Error (702, loc,
338                                                           "A constraint cannot be special class `{0}'",
339                                                       TypeManager.CSharpName (class_constraint_type));
340                                         return false;
341                                 }
342                         }
343
344                         if (class_constraint_type != null)
345                                 effective_base_type = class_constraint_type;
346                         else if (HasValueTypeConstraint)
347                                 effective_base_type = TypeManager.value_type;
348                         else
349                                 effective_base_type = TypeManager.object_type;
350
351                         if ((attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
352                                 attrs |= GenericParameterAttributes.DefaultConstructorConstraint;
353
354                         resolved = true;
355                         return true;
356                 }
357
358                 bool CheckTypeParameterConstraints (TypeParameter tparam, ref TypeExpr prevConstraint, ArrayList seen)
359                 {
360                         seen.Add (tparam);
361
362                         Constraints constraints = tparam.Constraints;
363                         if (constraints == null)
364                                 return true;
365
366                         if (constraints.HasValueTypeConstraint) {
367                                 Report.Error (456, loc,
368                                         "Type parameter `{0}' has the `struct' constraint, so it cannot be used as a constraint for `{1}'",
369                                         tparam.Name, name);
370                                 return false;
371                         }
372
373                         //
374                         //  Checks whether there are no conflicts between type parameter constraints
375                         //
376                         //   class Foo<T, U>
377                         //      where T : A
378                         //      where U : A, B  // A and B are not convertible
379                         //
380                         if (constraints.HasClassConstraint) {
381                                 if (prevConstraint != null) {
382                                         Type t2 = constraints.ClassConstraint;
383                                         TypeExpr e2 = constraints.class_constraint;
384
385                                         if (!Convert.ImplicitReferenceConversionExists (prevConstraint, t2) &&
386                                                 !Convert.ImplicitReferenceConversionExists (e2, prevConstraint.Type)) {
387                                                 Report.Error (455, loc,
388                                                         "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'",
389                                                         name, TypeManager.CSharpName (prevConstraint.Type), TypeManager.CSharpName (t2));
390                                                 return false;
391                                         }
392                                 }
393
394                                 prevConstraint = constraints.class_constraint;
395                         }
396
397                         if (constraints.type_param_constraints == null)
398                                 return true;
399
400                         foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
401                                 if (seen.Contains (expr.TypeParameter)) {
402                                         Report.Error (454, loc, "Circular constraint " +
403                                                       "dependency involving `{0}' and `{1}'",
404                                                       tparam.Name, expr.GetSignatureForError ());
405                                         return false;
406                                 }
407
408                                 if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prevConstraint, seen))
409                                         return false;
410                         }
411
412                         return true;
413                 }
414
415                 /// <summary>
416                 ///   Resolve the constraints into actual types.
417                 /// </summary>
418                 public bool ResolveTypes (IResolveContext ec)
419                 {
420                         if (resolved_types)
421                                 return true;
422
423                         resolved_types = true;
424
425                         foreach (object obj in constraints) {
426                                 GenericTypeExpr cexpr = obj as GenericTypeExpr;
427                                 if (cexpr == null)
428                                         continue;
429
430                                 if (!cexpr.CheckConstraints (ec))
431                                         return false;
432                         }
433
434                         if (type_param_constraints.Count != 0) {
435                                 ArrayList seen = new ArrayList ();
436                                 TypeExpr prev_constraint = class_constraint;
437                                 foreach (TypeParameterExpr expr in type_param_constraints) {
438                                         if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prev_constraint, seen))
439                                                 return false;
440                                         seen.Clear ();
441                                 }
442                         }
443
444                         for (int i = 0; i < iface_constraints.Count; ++i) {
445                                 TypeExpr iface_constraint = (TypeExpr) iface_constraints [i];
446                                 iface_constraint = iface_constraint.ResolveAsTypeTerminal (ec, false);
447                                 if (iface_constraint == null)
448                                         return false;
449                                 iface_constraints [i] = iface_constraint;
450                         }
451
452                         if (class_constraint != null) {
453                                 class_constraint = class_constraint.ResolveAsTypeTerminal (ec, false);
454                                 if (class_constraint == null)
455                                         return false;
456                         }
457
458                         return true;
459                 }
460
461                 public override GenericParameterAttributes Attributes {
462                         get { return attrs; }
463                 }
464
465                 public override bool HasClassConstraint {
466                         get { return class_constraint != null; }
467                 }
468
469                 public override Type ClassConstraint {
470                         get { return class_constraint_type; }
471                 }
472
473                 public override Type[] InterfaceConstraints {
474                         get { return iface_constraint_types; }
475                 }
476
477                 public override Type EffectiveBaseClass {
478                         get { return effective_base_type; }
479                 }
480
481                 public bool IsSubclassOf (Type t)
482                 {
483                         if ((class_constraint_type != null) &&
484                             class_constraint_type.IsSubclassOf (t))
485                                 return true;
486
487                         if (iface_constraint_types == null)
488                                 return false;
489
490                         foreach (Type iface in iface_constraint_types) {
491                                 if (TypeManager.IsSubclassOf (iface, t))
492                                         return true;
493                         }
494
495                         return false;
496                 }
497
498                 public Location Location {
499                         get {
500                                 return loc;
501                         }
502                 }
503
504                 /// <summary>
505                 ///   This is used when we're implementing a generic interface method.
506                 ///   Each method type parameter in implementing method must have the same
507                 ///   constraints than the corresponding type parameter in the interface
508                 ///   method.  To do that, we're called on each of the implementing method's
509                 ///   type parameters.
510                 /// </summary>
511                 public bool AreEqual (GenericConstraints gc)
512                 {
513                         if (gc.Attributes != attrs)
514                                 return false;
515
516                         if (HasClassConstraint != gc.HasClassConstraint)
517                                 return false;
518                         if (HasClassConstraint && !TypeManager.IsEqual (gc.ClassConstraint, ClassConstraint))
519                                 return false;
520
521                         int gc_icount = gc.InterfaceConstraints != null ?
522                                 gc.InterfaceConstraints.Length : 0;
523                         int icount = InterfaceConstraints != null ?
524                                 InterfaceConstraints.Length : 0;
525
526                         if (gc_icount != icount)
527                                 return false;
528
529                         for (int i = 0; i < gc.InterfaceConstraints.Length; ++i) {
530                                 Type iface = gc.InterfaceConstraints [i];
531                                 if (iface.IsGenericType)
532                                         iface = iface.GetGenericTypeDefinition ();
533                                 
534                                 bool ok = false;
535                                 for (int ii = 0; i < InterfaceConstraints.Length; ++ii) {
536                                         Type check = InterfaceConstraints [ii];
537                                         if (check.IsGenericType)
538                                                 check = check.GetGenericTypeDefinition ();
539                                         
540                                         if (TypeManager.IsEqual (iface, check)) {
541                                                 ok = true;
542                                                 break;
543                                         }
544                                 }
545
546                                 if (!ok)
547                                         return false;
548                         }
549
550                         return true;
551                 }
552
553                 public void VerifyClsCompliance ()
554                 {
555                         if (class_constraint_type != null && !AttributeTester.IsClsCompliant (class_constraint_type))
556                                 Warning_ConstrainIsNotClsCompliant (class_constraint_type, class_constraint.Location);
557
558                         if (iface_constraint_types != null) {
559                                 for (int i = 0; i < iface_constraint_types.Length; ++i) {
560                                         if (!AttributeTester.IsClsCompliant (iface_constraint_types [i]))
561                                                 Warning_ConstrainIsNotClsCompliant (iface_constraint_types [i],
562                                                         ((TypeExpr)iface_constraints [i]).Location);
563                                 }
564                         }
565                 }
566
567                 void Warning_ConstrainIsNotClsCompliant (Type t, Location loc)
568                 {
569                         Report.SymbolRelatedToPreviousError (t);
570                         Report.Warning (3024, 1, loc, "Constraint type `{0}' is not CLS-compliant",
571                                 TypeManager.CSharpName (t));
572                 }
573         }
574
575         /// <summary>
576         ///   A type parameter from a generic type definition.
577         /// </summary>
578         public class TypeParameter : MemberCore, IMemberContainer
579         {
580                 static readonly string[] attribute_target = new string [] { "type parameter" };
581                 
582                 DeclSpace decl;
583                 GenericConstraints gc;
584                 Constraints constraints;
585                 GenericTypeParameterBuilder type;
586                 MemberCache member_cache;
587                 Variance variance;
588
589                 public TypeParameter (DeclSpace parent, DeclSpace decl, string name,
590                                       Constraints constraints, Attributes attrs, Variance variance, Location loc)
591                         : base (parent, new MemberName (name, loc), attrs)
592                 {
593                         this.decl = decl;
594                         this.constraints = constraints;
595                         this.variance = variance;
596                         if (variance != Variance.None && !(decl is Interface) && !(decl is Delegate)) {
597                                 Report.Error (-36, loc, "Generic variance can only be used with interfaces and delegates");
598                         }
599                 }
600
601                 public GenericConstraints GenericConstraints {
602                         get { return gc != null ? gc : constraints; }
603                 }
604
605                 public Constraints Constraints {
606                         get { return constraints; }
607                 }
608
609                 public DeclSpace DeclSpace {
610                         get { return decl; }
611                 }
612
613                 public Variance Variance {
614                         get { return variance; }
615                 }
616
617                 public Type Type {
618                         get { return type; }
619                 }
620
621                 /// <summary>
622                 ///   This is the first method which is called during the resolving
623                 ///   process; we're called immediately after creating the type parameters
624                 ///   with SRE (by calling `DefineGenericParameters()' on the TypeBuilder /
625                 ///   MethodBuilder).
626                 ///
627                 ///   We're either called from TypeContainer.DefineType() or from
628                 ///   GenericMethod.Define() (called from Method.Define()).
629                 /// </summary>
630                 public void Define (GenericTypeParameterBuilder type)
631                 {
632                         if (this.type != null)
633                                 throw new InvalidOperationException ();
634
635                         this.type = type;
636                         TypeManager.AddTypeParameter (type, this);
637                 }
638
639                 /// <summary>
640                 ///   This is the second method which is called during the resolving
641                 ///   process - in case of class type parameters, we're called from
642                 ///   TypeContainer.ResolveType() - after it resolved the class'es
643                 ///   base class and interfaces. For method type parameters, we're
644                 ///   called immediately after Define().
645                 ///
646                 ///   We're just resolving the constraints into expressions here, we
647                 ///   don't resolve them into actual types.
648                 ///
649                 ///   Note that in the special case of partial generic classes, we may be
650                 ///   called _before_ Define() and we may also be called multiple types.
651                 /// </summary>
652                 public bool Resolve (DeclSpace ds)
653                 {
654                         if (constraints != null) {
655                                 if (!constraints.Resolve (ds)) {
656                                         constraints = null;
657                                         return false;
658                                 }
659                         }
660
661                         return true;
662                 }
663
664                 /// <summary>
665                 ///   This is the third method which is called during the resolving
666                 ///   process.  We're called immediately after calling DefineConstraints()
667                 ///   on all of the current class'es type parameters.
668                 ///
669                 ///   Our job is to resolve the constraints to actual types.
670                 ///
671                 ///   Note that we may have circular dependencies on type parameters - this
672                 ///   is why Resolve() and ResolveType() are separate.
673                 /// </summary>
674                 public bool ResolveType (IResolveContext ec)
675                 {
676                         if (constraints != null) {
677                                 if (!constraints.ResolveTypes (ec)) {
678                                         constraints = null;
679                                         return false;
680                                 }
681                         }
682
683                         return true;
684                 }
685
686                 /// <summary>
687                 ///   This is the fourth and last method which is called during the resolving
688                 ///   process.  We're called after everything is fully resolved and actually
689                 ///   register the constraints with SRE and the TypeManager.
690                 /// </summary>
691                 public bool DefineType (IResolveContext ec)
692                 {
693                         return DefineType (ec, null, null, false);
694                 }
695
696                 /// <summary>
697                 ///   This is the fith and last method which is called during the resolving
698                 ///   process.  We're called after everything is fully resolved and actually
699                 ///   register the constraints with SRE and the TypeManager.
700                 ///
701                 ///   The `builder', `implementing' and `is_override' arguments are only
702                 ///   applicable to method type parameters.
703                 /// </summary>
704                 public bool DefineType (IResolveContext ec, MethodBuilder builder,
705                                         MethodInfo implementing, bool is_override)
706                 {
707                         if (!ResolveType (ec))
708                                 return false;
709
710                         if (implementing != null) {
711                                 if (is_override && (constraints != null)) {
712                                         Report.Error (460, Location,
713                                                 "`{0}': Cannot specify constraints for overrides or explicit interface implementation methods",
714                                                 TypeManager.CSharpSignature (builder));
715                                         return false;
716                                 }
717
718                                 MethodBase mb = TypeManager.DropGenericMethodArguments (implementing);
719
720                                 int pos = type.GenericParameterPosition;
721                                 Type mparam = mb.GetGenericArguments () [pos];
722                                 GenericConstraints temp_gc = ReflectionConstraints.GetConstraints (mparam);
723
724                                 if (temp_gc != null)
725                                         gc = new InflatedConstraints (temp_gc, implementing.DeclaringType);
726                                 else if (constraints != null)
727                                         gc = new InflatedConstraints (constraints, implementing.DeclaringType);
728
729                                 bool ok = true;
730                                 if (constraints != null) {
731                                         if (temp_gc == null)
732                                                 ok = false;
733                                         else if (!constraints.AreEqual (gc))
734                                                 ok = false;
735                                 } else {
736                                         if (!is_override && (temp_gc != null))
737                                                 ok = false;
738                                 }
739
740                                 if (!ok) {
741                                         Report.SymbolRelatedToPreviousError (implementing);
742
743                                         Report.Error (
744                                                 425, Location, "The constraints for type " +
745                                                 "parameter `{0}' of method `{1}' must match " +
746                                                 "the constraints for type parameter `{2}' " +
747                                                 "of interface method `{3}'. Consider using " +
748                                                 "an explicit interface implementation instead",
749                                                 Name, TypeManager.CSharpSignature (builder),
750                                                 TypeManager.CSharpName (mparam), TypeManager.CSharpSignature (mb));
751                                         return false;
752                                 }
753                         } else if (DeclSpace is CompilerGeneratedClass) {
754                                 TypeParameter[] tparams = DeclSpace.TypeParameters;
755                                 Type[] types = new Type [tparams.Length];
756                                 for (int i = 0; i < tparams.Length; i++)
757                                         types [i] = tparams [i].Type;
758
759                                 if (constraints != null)
760                                         gc = new InflatedConstraints (constraints, types);
761                         } else {
762                                 gc = (GenericConstraints) constraints;
763                         }
764
765                         SetConstraints (type);
766                         return true;
767                 }
768
769                 public void SetConstraints (GenericTypeParameterBuilder type)
770                 {
771                         GenericParameterAttributes attr = GenericParameterAttributes.None;
772                         if (variance == Variance.Contravariant)
773                                 attr |= GenericParameterAttributes.Contravariant;
774                         else if (variance == Variance.Covariant)
775                                 attr |= GenericParameterAttributes.Covariant;
776
777                         if (gc != null) {
778                                 if (gc.HasClassConstraint || gc.HasValueTypeConstraint)
779                                         type.SetBaseTypeConstraint (gc.EffectiveBaseClass);
780
781                                 attr |= gc.Attributes;
782                                 type.SetInterfaceConstraints (gc.InterfaceConstraints);
783                                 TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
784                         }
785                         
786                         type.SetGenericParameterAttributes (attr);
787                 }
788
789                 /// <summary>
790                 ///   This is called for each part of a partial generic type definition.
791                 ///
792                 ///   If `new_constraints' is not null and we don't already have constraints,
793                 ///   they become our constraints.  If we already have constraints, we must
794                 ///   check that they're the same.
795                 ///   con
796                 /// </summary>
797                 public bool UpdateConstraints (IResolveContext ec, Constraints new_constraints)
798                 {
799                         if (type == null)
800                                 throw new InvalidOperationException ();
801
802                         if (new_constraints == null)
803                                 return true;
804
805                         if (!new_constraints.Resolve (ec))
806                                 return false;
807                         if (!new_constraints.ResolveTypes (ec))
808                                 return false;
809
810                         if (constraints != null) 
811                                 return constraints.AreEqual (new_constraints);
812
813                         constraints = new_constraints;
814                         return true;
815                 }
816
817                 public override void Emit ()
818                 {
819                         if (OptAttributes != null)
820                                 OptAttributes.Emit ();
821
822                         base.Emit ();
823                 }
824
825                 public override string DocCommentHeader {
826                         get {
827                                 throw new InvalidOperationException (
828                                         "Unexpected attempt to get doc comment from " + this.GetType () + ".");
829                         }
830                 }
831
832                 //
833                 // MemberContainer
834                 //
835
836                 public override bool Define ()
837                 {
838                         return true;
839                 }
840
841                 public override void ApplyAttributeBuilder (Attribute a,
842                                                             CustomAttributeBuilder cb)
843                 {
844                         type.SetCustomAttribute (cb);
845                 }
846
847                 public override AttributeTargets AttributeTargets {
848                         get {
849                                 return AttributeTargets.GenericParameter;
850                         }
851                 }
852
853                 public override string[] ValidAttributeTargets {
854                         get {
855                                 return attribute_target;
856                         }
857                 }
858
859                 //
860                 // IMemberContainer
861                 //
862
863                 string IMemberContainer.Name {
864                         get { return Name; }
865                 }
866
867                 MemberCache IMemberContainer.BaseCache {
868                         get {
869                                 if (gc == null)
870                                         return null;
871
872                                 if (gc.EffectiveBaseClass.BaseType == null)
873                                         return null;
874
875                                 return TypeManager.LookupMemberCache (gc.EffectiveBaseClass.BaseType);
876                         }
877                 }
878
879                 bool IMemberContainer.IsInterface {
880                         get { return false; }
881                 }
882
883                 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
884                 {
885                         throw new NotSupportedException ();
886                 }
887
888                 public MemberCache MemberCache {
889                         get {
890                                 if (member_cache != null)
891                                         return member_cache;
892
893                                 if (gc == null)
894                                         return null;
895
896                                 Type[] ifaces = TypeManager.ExpandInterfaces (gc.InterfaceConstraints);
897                                 member_cache = new MemberCache (this, gc.EffectiveBaseClass, ifaces);
898
899                                 return member_cache;
900                         }
901                 }
902
903                 public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
904                                                MemberFilter filter, object criteria)
905                 {
906                         if (gc == null)
907                                 return MemberList.Empty;
908
909                         ArrayList members = new ArrayList ();
910
911                         if (gc.HasClassConstraint) {
912                                 MemberList list = TypeManager.FindMembers (
913                                         gc.ClassConstraint, mt, bf, filter, criteria);
914
915                                 members.AddRange (list);
916                         }
917
918                         Type[] ifaces = TypeManager.ExpandInterfaces (gc.InterfaceConstraints);
919                         foreach (Type t in ifaces) {
920                                 MemberList list = TypeManager.FindMembers (
921                                         t, mt, bf, filter, criteria);
922
923                                 members.AddRange (list);
924                         }
925
926                         return new MemberList (members);
927                 }
928
929                 public bool IsSubclassOf (Type t)
930                 {
931                         if (type.Equals (t))
932                                 return true;
933
934                         if (constraints != null)
935                                 return constraints.IsSubclassOf (t);
936
937                         return false;
938                 }
939
940                 public void InflateConstraints (Type declaring)
941                 {
942                         if (constraints != null)
943                                 gc = new InflatedConstraints (constraints, declaring);
944                 }
945                 
946                 public override bool IsClsComplianceRequired ()
947                 {
948                         return false;
949                 }
950
951                 protected class InflatedConstraints : GenericConstraints
952                 {
953                         GenericConstraints gc;
954                         Type base_type;
955                         Type class_constraint;
956                         Type[] iface_constraints;
957                         Type[] dargs;
958
959                         public InflatedConstraints (GenericConstraints gc, Type declaring)
960                                 : this (gc, TypeManager.GetTypeArguments (declaring))
961                         { }
962
963                         public InflatedConstraints (GenericConstraints gc, Type[] dargs)
964                         {
965                                 this.gc = gc;
966                                 this.dargs = dargs;
967
968                                 ArrayList list = new ArrayList ();
969                                 if (gc.HasClassConstraint)
970                                         list.Add (inflate (gc.ClassConstraint));
971                                 foreach (Type iface in gc.InterfaceConstraints)
972                                         list.Add (inflate (iface));
973
974                                 bool has_class_constr = false;
975                                 if (list.Count > 0) {
976                                         Type first = (Type) list [0];
977                                         has_class_constr = !first.IsGenericParameter && !first.IsInterface;
978                                 }
979
980                                 if ((list.Count > 0) && has_class_constr) {
981                                         class_constraint = (Type) list [0];
982                                         iface_constraints = new Type [list.Count - 1];
983                                         list.CopyTo (1, iface_constraints, 0, list.Count - 1);
984                                 } else {
985                                         iface_constraints = new Type [list.Count];
986                                         list.CopyTo (iface_constraints, 0);
987                                 }
988
989                                 if (HasValueTypeConstraint)
990                                         base_type = TypeManager.value_type;
991                                 else if (class_constraint != null)
992                                         base_type = class_constraint;
993                                 else
994                                         base_type = TypeManager.object_type;
995                         }
996
997                         Type inflate (Type t)
998                         {
999                                 if (t == null)
1000                                         return null;
1001                                 if (t.IsGenericParameter)
1002                                         return t.GenericParameterPosition < dargs.Length ? dargs [t.GenericParameterPosition] : t;
1003                                 if (t.IsGenericType) {
1004                                         Type[] args = t.GetGenericArguments ();
1005                                         Type[] inflated = new Type [args.Length];
1006
1007                                         for (int i = 0; i < args.Length; i++)
1008                                                 inflated [i] = inflate (args [i]);
1009
1010                                         t = t.GetGenericTypeDefinition ();
1011                                         t = t.MakeGenericType (inflated);
1012                                 }
1013
1014                                 return t;
1015                         }
1016
1017                         public override string TypeParameter {
1018                                 get { return gc.TypeParameter; }
1019                         }
1020
1021                         public override GenericParameterAttributes Attributes {
1022                                 get { return gc.Attributes; }
1023                         }
1024
1025                         public override Type ClassConstraint {
1026                                 get { return class_constraint; }
1027                         }
1028
1029                         public override Type EffectiveBaseClass {
1030                                 get { return base_type; }
1031                         }
1032
1033                         public override Type[] InterfaceConstraints {
1034                                 get { return iface_constraints; }
1035                         }
1036                 }
1037         }
1038
1039         /// <summary>
1040         ///   A TypeExpr which already resolved to a type parameter.
1041         /// </summary>
1042         public class TypeParameterExpr : TypeExpr {
1043                 TypeParameter type_parameter;
1044
1045                 public TypeParameter TypeParameter {
1046                         get {
1047                                 return type_parameter;
1048                         }
1049                 }
1050                 
1051                 public TypeParameterExpr (TypeParameter type_parameter, Location loc)
1052                 {
1053                         this.type_parameter = type_parameter;
1054                         this.loc = loc;
1055                 }
1056
1057                 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
1058                 {
1059                         throw new NotSupportedException ();
1060                 }
1061
1062                 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
1063                 {
1064                         type = type_parameter.Type;
1065                         eclass = ExprClass.TypeParameter;
1066                         return this;
1067                 }
1068
1069                 public override bool IsInterface {
1070                         get { return false; }
1071                 }
1072
1073                 public override bool CheckAccessLevel (DeclSpace ds)
1074                 {
1075                         return true;
1076                 }
1077         }
1078
1079         //
1080         // Tracks the type arguments when instantiating a generic type. It's used
1081         // by both type arguments and type parameters
1082         //
1083         public class TypeArguments {
1084                 ArrayList args;
1085                 Type[] atypes;
1086                 
1087                 public TypeArguments ()
1088                 {
1089                         args = new ArrayList ();
1090                 }
1091
1092                 public TypeArguments (params FullNamedExpression[] types)
1093                 {
1094                         this.args = new ArrayList (types);
1095                 }
1096
1097                 public void Add (FullNamedExpression type)
1098                 {
1099                         args.Add (type);
1100                 }
1101
1102                 public void Add (TypeArguments new_args)
1103                 {
1104                         args.AddRange (new_args.args);
1105                 }
1106
1107                 // TODO: Should be deleted
1108                 public TypeParameterName[] GetDeclarations ()
1109                 {
1110                         return (TypeParameterName[]) args.ToArray (typeof (TypeParameterName));
1111                 }
1112
1113                 /// <summary>
1114                 ///   We may only be used after Resolve() is called and return the fully
1115                 ///   resolved types.
1116                 /// </summary>
1117                 public Type[] Arguments {
1118                         get {
1119                                 return atypes;
1120                         }
1121                 }
1122
1123                 public int Count {
1124                         get {
1125                                 return args.Count;
1126                         }
1127                 }
1128
1129                 public string GetSignatureForError()
1130                 {
1131                         StringBuilder sb = new StringBuilder();
1132                         for (int i = 0; i < Count; ++i)
1133                         {
1134                                 Expression expr = (Expression)args [i];
1135                                 sb.Append(expr.GetSignatureForError());
1136                                 if (i + 1 < Count)
1137                                         sb.Append(',');
1138                         }
1139                         return sb.ToString();
1140                 }
1141
1142                 /// <summary>
1143                 ///   Resolve the type arguments.
1144                 /// </summary>
1145                 public bool Resolve (IResolveContext ec)
1146                 {
1147                         if (atypes != null)
1148                                 return atypes.Length != 0;
1149
1150                         int count = args.Count;
1151                         bool ok = true;
1152
1153                         atypes = new Type [count];
1154
1155                         for (int i = 0; i < count; i++){
1156                                 TypeExpr te = ((FullNamedExpression) args[i]).ResolveAsTypeTerminal (ec, false);
1157                                 if (te == null) {
1158                                         ok = false;
1159                                         continue;
1160                                 }
1161
1162                                 atypes[i] = te.Type;
1163
1164                                 if (te.Type.IsSealed && te.Type.IsAbstract) {
1165                                         Report.Error (718, te.Location, "`{0}': static classes cannot be used as generic arguments",
1166                                                 te.GetSignatureForError ());
1167                                         ok = false;
1168                                 }
1169
1170                                 if (te.Type.IsPointer || TypeManager.IsSpecialType (te.Type)) {
1171                                         Report.Error (306, te.Location,
1172                                                 "The type `{0}' may not be used as a type argument",
1173                                                 te.GetSignatureForError ());
1174                                         ok = false;
1175                                 }
1176                         }
1177
1178                         if (!ok)
1179                                 atypes = Type.EmptyTypes;
1180
1181                         return ok;
1182                 }
1183
1184                 public TypeArguments Clone ()
1185                 {
1186                         TypeArguments copy = new TypeArguments ();
1187                         foreach (Expression ta in args)
1188                                 copy.args.Add (ta);
1189
1190                         return copy;
1191                 }
1192         }
1193
1194         public class TypeParameterName : SimpleName
1195         {
1196                 Attributes attributes;
1197                 Variance variance;
1198
1199                 public TypeParameterName (string name, Attributes attrs, Location loc)
1200                         : this (name, attrs, Variance.None, loc)
1201                 {
1202                 }
1203
1204                 public TypeParameterName (string name, Attributes attrs, Variance variance, Location loc)
1205                         : base (name, loc)
1206                 {
1207                         attributes = attrs;
1208                         this.variance = variance;
1209                 }
1210
1211                 public Attributes OptAttributes {
1212                         get {
1213                                 return attributes;
1214                         }
1215                 }
1216
1217                 public Variance Variance {
1218                         get {
1219                                 return variance;
1220                         }
1221                 }
1222         }
1223
1224         /// <summary>
1225         ///   A reference expression to generic type
1226         /// </summary>  
1227         class GenericTypeExpr : TypeExpr
1228         {
1229                 TypeArguments args;
1230                 Type[] gen_params;      // TODO: Waiting for constrains check cleanup
1231                 Type open_type;
1232
1233                 //
1234                 // Should be carefully used only with defined generic containers. Type parameters
1235                 // can be used as type arguments in this case.
1236                 //
1237                 // TODO: This could be GenericTypeExpr specialization
1238                 //
1239                 public GenericTypeExpr (DeclSpace gType, Location l)
1240                 {
1241                         open_type = gType.TypeBuilder.GetGenericTypeDefinition ();
1242
1243                         args = new TypeArguments ();
1244                         foreach (TypeParameter type_param in gType.TypeParameters)
1245                                 args.Add (new TypeParameterExpr (type_param, l));
1246
1247                         this.loc = l;
1248                 }
1249
1250                 /// <summary>
1251                 ///   Instantiate the generic type `t' with the type arguments `args'.
1252                 ///   Use this constructor if you already know the fully resolved
1253                 ///   generic type.
1254                 /// </summary>          
1255                 public GenericTypeExpr (Type t, TypeArguments args, Location l)
1256                 {
1257                         open_type = t.GetGenericTypeDefinition ();
1258
1259                         loc = l;
1260                         this.args = args;
1261                 }
1262
1263                 public TypeArguments TypeArguments {
1264                         get { return args; }
1265                 }
1266
1267                 public override string GetSignatureForError ()
1268                 {
1269                         return TypeManager.CSharpName (type);
1270                 }
1271
1272                 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
1273                 {
1274                         if (eclass != ExprClass.Invalid)
1275                                 return this;
1276
1277                         eclass = ExprClass.Type;
1278
1279                         if (!args.Resolve (ec))
1280                                 return null;
1281
1282                         gen_params = open_type.GetGenericArguments ();
1283                         Type[] atypes = args.Arguments;
1284                         
1285                         if (atypes.Length != gen_params.Length) {
1286                                 Namespace.Error_InvalidNumberOfTypeArguments (open_type, loc);
1287                                 return null;
1288                         }
1289
1290                         //
1291                         // Now bind the parameters
1292                         //
1293                         type = open_type.MakeGenericType (atypes);
1294                         return this;
1295                 }
1296
1297                 /// <summary>
1298                 ///   Check the constraints; we're called from ResolveAsTypeTerminal()
1299                 ///   after fully resolving the constructed type.
1300                 /// </summary>
1301                 public bool CheckConstraints (IResolveContext ec)
1302                 {
1303                         return ConstraintChecker.CheckConstraints (ec, open_type, gen_params, args.Arguments, loc);
1304                 }
1305
1306                 static bool IsVariant (Type type)
1307                 {
1308                         return (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) != 0;
1309                 }
1310         
1311                 static bool IsCovariant (Type type)
1312                 {
1313                         return (type.GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0;
1314                 }
1315         
1316                 static bool IsContravariant (Type type)
1317                 {
1318                         return (type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0;
1319                 }
1320         
1321                 public bool VerifyVariantTypeParameters ()
1322                 {
1323                         for (int i = 0; i < args.Count; i++) {
1324                                 Type argument = args.Arguments[i];
1325                                 if (argument.IsGenericParameter && IsVariant (argument)) {
1326                                         if (IsContravariant (argument) && !IsContravariant (gen_params[i])) {
1327                                                 Report.Error (-34, loc, "Contravariant type parameters can only be used " +
1328                                               "as type arguments in contravariant positions");
1329                                                 return false;
1330                                         }
1331                                         else if (IsCovariant (argument) && !IsCovariant (gen_params[i])) {
1332                                                 Report.Error (-35, loc, "Covariant type parameters can only be used " +
1333                                               "as type arguments in covariant positions");
1334                                                 return false;
1335                                         }
1336                                 }
1337                         }
1338                         return true;
1339                 }
1340
1341                 
1342                 public override bool CheckAccessLevel (DeclSpace ds)
1343                 {
1344                         return ds.CheckAccessLevel (open_type);
1345                 }
1346
1347                 public override bool AsAccessible (DeclSpace ds)
1348                 {
1349                         foreach (Type t in args.Arguments) {
1350                                 if (!ds.IsAccessibleAs (t))
1351                                         return false;
1352                         }
1353
1354                         return ds.IsAccessibleAs (open_type);
1355                 }
1356
1357                 public override bool IsClass {
1358                         get { return open_type.IsClass; }
1359                 }
1360
1361                 public override bool IsValueType {
1362                         get { return TypeManager.IsStruct (open_type); }
1363                 }
1364
1365                 public override bool IsInterface {
1366                         get { return open_type.IsInterface; }
1367                 }
1368
1369                 public override bool IsSealed {
1370                         get { return open_type.IsSealed; }
1371                 }
1372
1373                 public override bool Equals (object obj)
1374                 {
1375                         GenericTypeExpr cobj = obj as GenericTypeExpr;
1376                         if (cobj == null)
1377                                 return false;
1378
1379                         if ((type == null) || (cobj.type == null))
1380                                 return false;
1381
1382                         return type == cobj.type;
1383                 }
1384
1385                 public override int GetHashCode ()
1386                 {
1387                         return base.GetHashCode ();
1388                 }
1389         }
1390
1391         public abstract class ConstraintChecker
1392         {
1393                 protected readonly Type[] gen_params;
1394                 protected readonly Type[] atypes;
1395                 protected readonly Location loc;
1396
1397                 protected ConstraintChecker (Type[] gen_params, Type[] atypes, Location loc)
1398                 {
1399                         this.gen_params = gen_params;
1400                         this.atypes = atypes;
1401                         this.loc = loc;
1402                 }
1403
1404                 /// <summary>
1405                 ///   Check the constraints; we're called from ResolveAsTypeTerminal()
1406                 ///   after fully resolving the constructed type.
1407                 /// </summary>
1408                 public bool CheckConstraints (IResolveContext ec)
1409                 {
1410                         for (int i = 0; i < gen_params.Length; i++) {
1411                                 if (!CheckConstraints (ec, i))
1412                                         return false;
1413                         }
1414
1415                         return true;
1416                 }
1417
1418                 protected bool CheckConstraints (IResolveContext ec, int index)
1419                 {
1420                         Type atype = atypes [index];
1421                         Type ptype = gen_params [index];
1422
1423                         if (atype == ptype)
1424                                 return true;
1425
1426                         Expression aexpr = new EmptyExpression (atype);
1427
1428                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (ptype);
1429                         if (gc == null)
1430                                 return true;
1431
1432                         bool is_class, is_struct;
1433                         if (atype.IsGenericParameter) {
1434                                 GenericConstraints agc = TypeManager.GetTypeParameterConstraints (atype);
1435                                 if (agc != null) {
1436                                         if (agc is Constraints)
1437                                                 ((Constraints) agc).Resolve (ec);
1438                                         is_class = agc.IsReferenceType;
1439                                         is_struct = agc.IsValueType;
1440                                 } else {
1441                                         is_class = is_struct = false;
1442                                 }
1443                         } else {
1444 #if MS_COMPATIBLE
1445                                 is_class = false;
1446                                 if (!atype.IsGenericType)
1447 #endif
1448                                 is_class = atype.IsClass || atype.IsInterface;
1449                                 is_struct = TypeManager.IsValueType (atype) && !TypeManager.IsNullableType (atype);
1450                         }
1451
1452                         //
1453                         // First, check the `class' and `struct' constraints.
1454                         //
1455                         if (gc.HasReferenceTypeConstraint && !is_class) {
1456                                 Report.Error (452, loc, "The type `{0}' must be " +
1457                                               "a reference type in order to use it " +
1458                                               "as type parameter `{1}' in the " +
1459                                               "generic type or method `{2}'.",
1460                                               TypeManager.CSharpName (atype),
1461                                               TypeManager.CSharpName (ptype),
1462                                               GetSignatureForError ());
1463                                 return false;
1464                         } else if (gc.HasValueTypeConstraint && !is_struct) {
1465                                 Report.Error (453, loc, "The type `{0}' must be a " +
1466                                               "non-nullable value type in order to use it " +
1467                                               "as type parameter `{1}' in the " +
1468                                               "generic type or method `{2}'.",
1469                                               TypeManager.CSharpName (atype),
1470                                               TypeManager.CSharpName (ptype),
1471                                               GetSignatureForError ());
1472                                 return false;
1473                         }
1474
1475                         //
1476                         // The class constraint comes next.
1477                         //
1478                         if (gc.HasClassConstraint) {
1479                                 if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint))
1480                                         return false;
1481                         }
1482
1483                         //
1484                         // Now, check the interface constraints.
1485                         //
1486                         if (gc.InterfaceConstraints != null) {
1487                                 foreach (Type it in gc.InterfaceConstraints) {
1488                                         if (!CheckConstraint (ec, ptype, aexpr, it))
1489                                                 return false;
1490                                 }
1491                         }
1492
1493                         //
1494                         // Finally, check the constructor constraint.
1495                         //
1496
1497                         if (!gc.HasConstructorConstraint)
1498                                 return true;
1499
1500                         if (TypeManager.IsBuiltinType (atype) || TypeManager.IsValueType (atype))
1501                                 return true;
1502
1503                         if (HasDefaultConstructor (atype))
1504                                 return true;
1505
1506                         Report_SymbolRelatedToPreviousError ();
1507                         Report.SymbolRelatedToPreviousError (atype);
1508                         Report.Error (310, loc, "The type `{0}' must have a public " +
1509                                       "parameterless constructor in order to use it " +
1510                                       "as parameter `{1}' in the generic type or " +
1511                                       "method `{2}'",
1512                                       TypeManager.CSharpName (atype),
1513                                       TypeManager.CSharpName (ptype),
1514                                       GetSignatureForError ());
1515                         return false;
1516                 }
1517
1518                 protected bool CheckConstraint (IResolveContext ec, Type ptype, Expression expr,
1519                                                 Type ctype)
1520                 {
1521                         if (TypeManager.HasGenericArguments (ctype)) {
1522                                 Type[] types = TypeManager.GetTypeArguments (ctype);
1523
1524                                 TypeArguments new_args = new TypeArguments ();
1525
1526                                 for (int i = 0; i < types.Length; i++) {
1527                                         Type t = types [i];
1528
1529                                         if (t.IsGenericParameter) {
1530                                                 int pos = t.GenericParameterPosition;
1531                                                 t = atypes [pos];
1532                                         }
1533                                         new_args.Add (new TypeExpression (t, loc));
1534                                 }
1535
1536                                 TypeExpr ct = new GenericTypeExpr (ctype, new_args, loc);
1537                                 if (ct.ResolveAsTypeStep (ec, false) == null)
1538                                         return false;
1539                                 ctype = ct.Type;
1540                         } else if (ctype.IsGenericParameter) {
1541                                 int pos = ctype.GenericParameterPosition;
1542                                 if (ctype.DeclaringMethod == null) {
1543                                         // FIXME: Implement
1544                                         return true;
1545                                 } else {                                
1546                                         ctype = atypes [pos];
1547                                 }
1548                         }
1549
1550                         if (Convert.ImplicitStandardConversionExists (expr, ctype))
1551                                 return true;
1552
1553                         Report_SymbolRelatedToPreviousError ();
1554                         Report.SymbolRelatedToPreviousError (expr.Type);
1555
1556                         if (TypeManager.IsNullableType (expr.Type) && ctype.IsInterface) {
1557                                 Report.Error (313, loc,
1558                                         "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. " +
1559                                         "The nullable type `{0}' never satisfies interface constraint of type `{3}'",
1560                                         TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ptype),
1561                                         GetSignatureForError (), TypeManager.CSharpName (ctype));
1562                         } else {
1563                                 Report.Error (309, loc,
1564                                         "The type `{0}' must be convertible to `{1}' in order to " +
1565                                         "use it as parameter `{2}' in the generic type or method `{3}'",
1566                                         TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ctype),
1567                                         TypeManager.CSharpName (ptype), GetSignatureForError ());
1568                         }
1569                         return false;
1570                 }
1571
1572                 static bool HasDefaultConstructor (Type atype)
1573                 {
1574                         TypeParameter tparam = TypeManager.LookupTypeParameter (atype);
1575                         if (tparam != null) {
1576                                 if (tparam.GenericConstraints == null)
1577                                         return false;
1578                                                 
1579                                 return tparam.GenericConstraints.HasConstructorConstraint || 
1580                                         tparam.GenericConstraints.HasValueTypeConstraint;
1581                         }
1582                 
1583                         if (atype.IsAbstract)
1584                                 return false;
1585
1586                 again:
1587                         atype = TypeManager.DropGenericTypeArguments (atype);
1588                         if (atype is TypeBuilder) {
1589                                 TypeContainer tc = TypeManager.LookupTypeContainer (atype);
1590                                 if (tc.InstanceConstructors == null) {
1591                                         atype = atype.BaseType;
1592                                         goto again;
1593                                 }
1594
1595                                 foreach (Constructor c in tc.InstanceConstructors) {
1596                                         if ((c.ModFlags & Modifiers.PUBLIC) == 0)
1597                                                 continue;
1598                                         if ((c.Parameters.FixedParameters != null) &&
1599                                             (c.Parameters.FixedParameters.Length != 0))
1600                                                 continue;
1601                                         if (c.Parameters.HasArglist || c.Parameters.HasParams)
1602                                                 continue;
1603
1604                                         return true;
1605                                 }
1606                         }
1607
1608                         MemberInfo [] list = TypeManager.MemberLookup (null, null, atype, MemberTypes.Constructor,
1609                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
1610                                 ConstructorInfo.ConstructorName, null);
1611
1612                         if (list == null)
1613                                 return false;
1614
1615                         foreach (MethodBase mb in list) {
1616                                 AParametersCollection pd = TypeManager.GetParameterData (mb);
1617                                 if (pd.Count == 0)
1618                                         return true;
1619                         }
1620
1621                         return false;
1622                 }
1623
1624                 protected abstract string GetSignatureForError ();
1625                 protected abstract void Report_SymbolRelatedToPreviousError ();
1626
1627                 public static bool CheckConstraints (EmitContext ec, MethodBase definition,
1628                                                      MethodBase instantiated, Location loc)
1629                 {
1630                         MethodConstraintChecker checker = new MethodConstraintChecker (
1631                                 definition, definition.GetGenericArguments (),
1632                                 instantiated.GetGenericArguments (), loc);
1633
1634                         return checker.CheckConstraints (ec);
1635                 }
1636
1637                 public static bool CheckConstraints (IResolveContext ec, Type gt, Type[] gen_params,
1638                                                      Type[] atypes, Location loc)
1639                 {
1640                         TypeConstraintChecker checker = new TypeConstraintChecker (
1641                                 gt, gen_params, atypes, loc);
1642
1643                         return checker.CheckConstraints (ec);
1644                 }
1645
1646                 protected class MethodConstraintChecker : ConstraintChecker
1647                 {
1648                         MethodBase definition;
1649
1650                         public MethodConstraintChecker (MethodBase definition, Type[] gen_params,
1651                                                         Type[] atypes, Location loc)
1652                                 : base (gen_params, atypes, loc)
1653                         {
1654                                 this.definition = definition;
1655                         }
1656
1657                         protected override string GetSignatureForError ()
1658                         {
1659                                 return TypeManager.CSharpSignature (definition);
1660                         }
1661
1662                         protected override void Report_SymbolRelatedToPreviousError ()
1663                         {
1664                                 Report.SymbolRelatedToPreviousError (definition);
1665                         }
1666                 }
1667
1668                 protected class TypeConstraintChecker : ConstraintChecker
1669                 {
1670                         Type gt;
1671
1672                         public TypeConstraintChecker (Type gt, Type[] gen_params, Type[] atypes,
1673                                                       Location loc)
1674                                 : base (gen_params, atypes, loc)
1675                         {
1676                                 this.gt = gt;
1677                         }
1678
1679                         protected override string GetSignatureForError ()
1680                         {
1681                                 return TypeManager.CSharpName (gt);
1682                         }
1683
1684                         protected override void Report_SymbolRelatedToPreviousError ()
1685                         {
1686                                 Report.SymbolRelatedToPreviousError (gt);
1687                         }
1688                 }
1689         }
1690
1691         /// <summary>
1692         ///   A generic method definition.
1693         /// </summary>
1694         public class GenericMethod : DeclSpace
1695         {
1696                 FullNamedExpression return_type;
1697                 ParametersCompiled parameters;
1698
1699                 public GenericMethod (NamespaceEntry ns, DeclSpace parent, MemberName name,
1700                                       FullNamedExpression return_type, ParametersCompiled parameters)
1701                         : base (ns, parent, name, null)
1702                 {
1703                         this.return_type = return_type;
1704                         this.parameters = parameters;
1705                 }
1706
1707                 public override TypeBuilder DefineType ()
1708                 {
1709                         throw new Exception ();
1710                 }
1711
1712                 public override bool Define ()
1713                 {
1714                         for (int i = 0; i < TypeParameters.Length; i++)
1715                                 if (!TypeParameters [i].Resolve (this))
1716                                         return false;
1717
1718                         return true;
1719                 }
1720
1721                 /// <summary>
1722                 ///   Define and resolve the type parameters.
1723                 ///   We're called from Method.Define().
1724                 /// </summary>
1725                 public bool Define (MethodOrOperator m)
1726                 {
1727                         TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
1728                         string[] snames = new string [names.Length];
1729                         for (int i = 0; i < names.Length; i++) {
1730                                 string type_argument_name = names[i].Name;
1731                                 int idx = parameters.GetParameterIndexByName (type_argument_name);
1732                                 if (idx >= 0) {
1733                                         Block b = m.Block;
1734                                         if (b == null)
1735                                                 b = new Block (null);
1736
1737                                         b.Error_AlreadyDeclaredTypeParameter (parameters [i].Location,
1738                                                 type_argument_name, "method parameter");
1739                                 }
1740                                 
1741                                 snames[i] = type_argument_name;
1742                         }
1743
1744                         GenericTypeParameterBuilder[] gen_params = m.MethodBuilder.DefineGenericParameters (snames);
1745                         for (int i = 0; i < TypeParameters.Length; i++)
1746                                 TypeParameters [i].Define (gen_params [i]);
1747
1748                         if (!Define ())
1749                                 return false;
1750
1751                         for (int i = 0; i < TypeParameters.Length; i++) {
1752                                 if (!TypeParameters [i].ResolveType (this))
1753                                         return false;
1754                         }
1755
1756                         return true;
1757                 }
1758
1759                 /// <summary>
1760                 ///   We're called from MethodData.Define() after creating the MethodBuilder.
1761                 /// </summary>
1762                 public bool DefineType (EmitContext ec, MethodBuilder mb,
1763                                         MethodInfo implementing, bool is_override)
1764                 {
1765                         for (int i = 0; i < TypeParameters.Length; i++)
1766                                 if (!TypeParameters [i].DefineType (
1767                                             ec, mb, implementing, is_override))
1768                                         return false;
1769
1770                         bool ok = parameters.Resolve (ec);
1771
1772                         if ((return_type != null) && (return_type.ResolveAsTypeTerminal (ec, false) == null))
1773                                 ok = false;
1774
1775                         return ok;
1776                 }
1777
1778                 public void EmitAttributes ()
1779                 {
1780                         for (int i = 0; i < TypeParameters.Length; i++)
1781                                 TypeParameters [i].Emit ();
1782
1783                         if (OptAttributes != null)
1784                                 OptAttributes.Emit ();
1785                 }
1786
1787                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1788                                                         MemberFilter filter, object criteria)
1789                 {
1790                         throw new Exception ();
1791                 }               
1792
1793                 public override MemberCache MemberCache {
1794                         get {
1795                                 return null;
1796                         }
1797                 }
1798
1799                 public override AttributeTargets AttributeTargets {
1800                         get {
1801                                 return AttributeTargets.Method | AttributeTargets.ReturnValue;
1802                         }
1803                 }
1804
1805                 public override string DocCommentHeader {
1806                         get { return "M:"; }
1807                 }
1808
1809                 public new void VerifyClsCompliance ()
1810                 {
1811                         foreach (TypeParameter tp in TypeParameters) {
1812                                 if (tp.Constraints == null)
1813                                         continue;
1814
1815                                 tp.Constraints.VerifyClsCompliance ();
1816                         }
1817                 }
1818         }
1819
1820         public partial class TypeManager
1821         {
1822                 static public Type activator_type;
1823         
1824                 public static TypeContainer LookupGenericTypeContainer (Type t)
1825                 {
1826                         t = DropGenericTypeArguments (t);
1827                         return LookupTypeContainer (t);
1828                 }
1829
1830                 /// <summary>
1831                 ///   Check whether `a' and `b' may become equal generic types.
1832                 ///   The algorithm to do that is a little bit complicated.
1833                 /// </summary>
1834                 public static bool MayBecomeEqualGenericTypes (Type a, Type b, Type[] class_inferred,
1835                                                                Type[] method_inferred)
1836                 {
1837                         if (a.IsGenericParameter) {
1838                                 //
1839                                 // If a is an array of a's type, they may never
1840                                 // become equal.
1841                                 //
1842                                 while (b.IsArray) {
1843                                         b = GetElementType (b);
1844                                         if (a.Equals (b))
1845                                                 return false;
1846                                 }
1847
1848                                 //
1849                                 // If b is a generic parameter or an actual type,
1850                                 // they may become equal:
1851                                 //
1852                                 //    class X<T,U> : I<T>, I<U>
1853                                 //    class X<T> : I<T>, I<float>
1854                                 // 
1855                                 if (b.IsGenericParameter || !b.IsGenericType) {
1856                                         int pos = a.GenericParameterPosition;
1857                                         Type[] args = a.DeclaringMethod != null ? method_inferred : class_inferred;
1858                                         if (args [pos] == null) {
1859                                                 args [pos] = b;
1860                                                 return true;
1861                                         }
1862
1863                                         return args [pos] == a;
1864                                 }
1865
1866                                 //
1867                                 // We're now comparing a type parameter with a
1868                                 // generic instance.  They may become equal unless
1869                                 // the type parameter appears anywhere in the
1870                                 // generic instance:
1871                                 //
1872                                 //    class X<T,U> : I<T>, I<X<U>>
1873                                 //        -> error because you could instanciate it as
1874                                 //           X<X<int>,int>
1875                                 //
1876                                 //    class X<T> : I<T>, I<X<T>> -> ok
1877                                 //
1878
1879                                 Type[] bargs = GetTypeArguments (b);
1880                                 for (int i = 0; i < bargs.Length; i++) {
1881                                         if (a.Equals (bargs [i]))
1882                                                 return false;
1883                                 }
1884
1885                                 return true;
1886                         }
1887
1888                         if (b.IsGenericParameter)
1889                                 return MayBecomeEqualGenericTypes (b, a, class_inferred, method_inferred);
1890
1891                         //
1892                         // At this point, neither a nor b are a type parameter.
1893                         //
1894                         // If one of them is a generic instance, let
1895                         // MayBecomeEqualGenericInstances() compare them (if the
1896                         // other one is not a generic instance, they can never
1897                         // become equal).
1898                         //
1899
1900                         if (a.IsGenericType || b.IsGenericType)
1901                                 return MayBecomeEqualGenericInstances (a, b, class_inferred, method_inferred);
1902
1903                         //
1904                         // If both of them are arrays.
1905                         //
1906
1907                         if (a.IsArray && b.IsArray) {
1908                                 if (a.GetArrayRank () != b.GetArrayRank ())
1909                                         return false;
1910                         
1911                                 a = GetElementType (a);
1912                                 b = GetElementType (b);
1913
1914                                 return MayBecomeEqualGenericTypes (a, b, class_inferred, method_inferred);
1915                         }
1916
1917                         //
1918                         // Ok, two ordinary types.
1919                         //
1920
1921                         return a.Equals (b);
1922                 }
1923
1924                 //
1925                 // Checks whether two generic instances may become equal for some
1926                 // particular instantiation (26.3.1).
1927                 //
1928                 public static bool MayBecomeEqualGenericInstances (Type a, Type b,
1929                                                                    Type[] class_inferred,
1930                                                                    Type[] method_inferred)
1931                 {
1932                         if (!a.IsGenericType || !b.IsGenericType)
1933                                 return false;
1934                         if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1935                                 return false;
1936
1937                         return MayBecomeEqualGenericInstances (
1938                                 GetTypeArguments (a), GetTypeArguments (b), class_inferred, method_inferred);
1939                 }
1940
1941                 public static bool MayBecomeEqualGenericInstances (Type[] aargs, Type[] bargs,
1942                                                                    Type[] class_inferred,
1943                                                                    Type[] method_inferred)
1944                 {
1945                         if (aargs.Length != bargs.Length)
1946                                 return false;
1947
1948                         for (int i = 0; i < aargs.Length; i++) {
1949                                 if (!MayBecomeEqualGenericTypes (aargs [i], bargs [i], class_inferred, method_inferred))
1950                                         return false;
1951                         }
1952
1953                         return true;
1954                 }
1955
1956                 /// <summary>
1957                 ///   Type inference.  Try to infer the type arguments from `method',
1958                 ///   which is invoked with the arguments `arguments'.  This is used
1959                 ///   when resolving an Invocation or a DelegateInvocation and the user
1960                 ///   did not explicitly specify type arguments.
1961                 /// </summary>
1962                 public static int InferTypeArguments (EmitContext ec,
1963                                                        ArrayList arguments,
1964                                                        ref MethodBase method)
1965                 {
1966                         ATypeInference ti = ATypeInference.CreateInstance (arguments);
1967                         Type[] i_args = ti.InferMethodArguments (ec, method);
1968                         if (i_args == null)
1969                                 return ti.InferenceScore;
1970
1971                         if (i_args.Length == 0)
1972                                 return 0;
1973
1974                         method = ((MethodInfo) method).MakeGenericMethod (i_args);
1975                         return 0;
1976                 }
1977
1978                 /// <summary>
1979                 ///   Type inference.
1980                 /// </summary>
1981                 public static bool InferTypeArguments (AParametersCollection apd,
1982                                                        ref MethodBase method)
1983                 {
1984                         if (!TypeManager.IsGenericMethod (method))
1985                                 return true;
1986
1987                         ATypeInference ti = ATypeInference.CreateInstance (ArrayList.Adapter (apd.Types));
1988                         Type[] i_args = ti.InferDelegateArguments (method);
1989                         if (i_args == null)
1990                                 return false;
1991
1992                         method = ((MethodInfo) method).MakeGenericMethod (i_args);
1993                         return true;
1994                 }
1995         }
1996
1997         abstract class ATypeInference
1998         {
1999                 protected readonly ArrayList arguments;
2000                 protected readonly int arg_count;
2001
2002                 protected ATypeInference (ArrayList arguments)
2003                 {
2004                         this.arguments = arguments;
2005                         if (arguments != null)
2006                                 arg_count = arguments.Count;
2007                 }
2008
2009                 public static ATypeInference CreateInstance (ArrayList arguments)
2010                 {
2011                         if (RootContext.Version == LanguageVersion.ISO_2)
2012                                 return new TypeInferenceV2 (arguments);
2013
2014                         return new TypeInferenceV3 (arguments);
2015                 }
2016
2017                 public virtual int InferenceScore {
2018                         get {
2019                                 return int.MaxValue;
2020                         }
2021                 }
2022
2023                 public abstract Type[] InferMethodArguments (EmitContext ec, MethodBase method);
2024                 public abstract Type[] InferDelegateArguments (MethodBase method);
2025         }
2026
2027         //
2028         // Implements C# 2.0 type inference
2029         //
2030         class TypeInferenceV2 : ATypeInference
2031         {
2032                 public TypeInferenceV2 (ArrayList arguments)
2033                         : base (arguments)
2034                 {
2035                 }
2036
2037                 public override Type[] InferDelegateArguments (MethodBase method)
2038                 {
2039                         AParametersCollection pd = TypeManager.GetParameterData (method);
2040                         if (arg_count != pd.Count)
2041                                 return null;
2042
2043                         Type[] method_args = method.GetGenericArguments ();
2044                         Type[] inferred_types = new Type[method_args.Length];
2045
2046                         Type[] param_types = new Type[pd.Count];
2047                         Type[] arg_types = (Type[])arguments.ToArray (typeof (Type));
2048
2049                         for (int i = 0; i < arg_count; i++) {
2050                                 param_types[i] = pd.Types [i];
2051                         }
2052
2053                         if (!InferTypeArguments (param_types, arg_types, inferred_types))
2054                                 return null;
2055
2056                         return inferred_types;
2057                 }
2058
2059                 public override Type[] InferMethodArguments (EmitContext ec, MethodBase method)
2060                 {
2061                         AParametersCollection pd = TypeManager.GetParameterData (method);
2062                         Type[] method_generic_args = method.GetGenericArguments ();
2063                         Type [] inferred_types = new Type [method_generic_args.Length];
2064                         Type[] arg_types = new Type [pd.Count];
2065
2066                         int a_count = arg_types.Length;
2067                         if (pd.HasParams)
2068                                 --a_count;
2069
2070                         for (int i = 0; i < a_count; i++) {
2071                                 Argument a = (Argument) arguments[i];
2072                                 if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
2073                                         continue;
2074
2075                                 if (!TypeInferenceV2.UnifyType (pd.Types [i], a.Type, inferred_types))
2076                                         return null;
2077                         }
2078
2079                         if (pd.HasParams) {
2080                                 Type element_type = TypeManager.GetElementType (pd.Types [a_count]);
2081                                 for (int i = a_count; i < arg_count; i++) {
2082                                         Argument a = (Argument) arguments [i];
2083                                         if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
2084                                                 continue;
2085
2086                                         if (!TypeInferenceV2.UnifyType (element_type, a.Type, inferred_types))
2087                                                 return null;
2088                                 }
2089                         }
2090
2091                         for (int i = 0; i < inferred_types.Length; i++)
2092                                 if (inferred_types [i] == null)
2093                                         return null;
2094
2095                         return inferred_types;
2096                 }
2097
2098                 static bool InferTypeArguments (Type[] param_types, Type[] arg_types,
2099                                 Type[] inferred_types)
2100                 {
2101                         for (int i = 0; i < arg_types.Length; i++) {
2102                                 if (arg_types[i] == null)
2103                                         continue;
2104
2105                                 if (!UnifyType (param_types[i], arg_types[i], inferred_types))
2106                                         return false;
2107                         }
2108
2109                         for (int i = 0; i < inferred_types.Length; ++i)
2110                                 if (inferred_types[i] == null)
2111                                         return false;
2112
2113                         return true;
2114                 }
2115
2116                 public static bool UnifyType (Type pt, Type at, Type[] inferred)
2117                 {
2118                         if (pt.IsGenericParameter) {
2119                                 if (pt.DeclaringMethod == null)
2120                                         return pt == at;
2121
2122                                 int pos = pt.GenericParameterPosition;
2123
2124                                 if (inferred [pos] == null)
2125                                         inferred [pos] = at;
2126
2127                                 return inferred [pos] == at;
2128                         }
2129
2130                         if (!pt.ContainsGenericParameters) {
2131                                 if (at.ContainsGenericParameters)
2132                                         return UnifyType (at, pt, inferred);
2133                                 else
2134                                         return true;
2135                         }
2136
2137                         if (at.IsArray) {
2138                                 if (pt.IsArray) {
2139                                         if (at.GetArrayRank () != pt.GetArrayRank ())
2140                                                 return false;
2141
2142                                         return UnifyType (TypeManager.GetElementType (pt), TypeManager.GetElementType (at), inferred);
2143                                 }
2144
2145                                 if (!pt.IsGenericType)
2146                                         return false;
2147
2148                                 Type gt = pt.GetGenericTypeDefinition ();
2149                                 if ((gt != TypeManager.generic_ilist_type) && (gt != TypeManager.generic_icollection_type) &&
2150                                         (gt != TypeManager.generic_ienumerable_type))
2151                                         return false;
2152
2153                                 Type[] args = TypeManager.GetTypeArguments (pt);
2154                                 return UnifyType (args[0], at.GetElementType (), inferred);
2155                         }
2156
2157                         if (pt.IsArray) {
2158                                 if (!at.IsArray ||
2159                                         (pt.GetArrayRank () != at.GetArrayRank ()))
2160                                         return false;
2161
2162                                 return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
2163                         }
2164
2165                         if (pt.IsByRef && at.IsByRef)
2166                                 return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
2167                         ArrayList list = new ArrayList ();
2168                         if (at.IsGenericType)
2169                                 list.Add (at);
2170                         for (Type bt = at.BaseType; bt != null; bt = bt.BaseType)
2171                                 list.Add (bt);
2172
2173                         list.AddRange (TypeManager.GetInterfaces (at));
2174
2175                         foreach (Type type in list) {
2176                                 if (!type.IsGenericType)
2177                                         continue;
2178
2179                                 if (TypeManager.DropGenericTypeArguments (pt) != TypeManager.DropGenericTypeArguments (type))
2180                                         continue;
2181
2182                                 if (!UnifyTypes (pt.GetGenericArguments (), type.GetGenericArguments (), inferred))
2183                                         return false;
2184                         }
2185
2186                         return true;
2187                 }
2188
2189                 static bool UnifyTypes (Type[] pts, Type[] ats, Type[] inferred)
2190                 {
2191                         for (int i = 0; i < ats.Length; i++) {
2192                                 if (!UnifyType (pts [i], ats [i], inferred))
2193                                         return false;
2194                         }
2195                         return true;
2196                 }
2197         }
2198
2199         //
2200         // Implements C# 3.0 type inference
2201         //
2202         class TypeInferenceV3 : ATypeInference
2203         {
2204                 //
2205                 // Tracks successful rate of type inference
2206                 //
2207                 int score = int.MaxValue;
2208
2209                 public TypeInferenceV3 (ArrayList arguments)
2210                         : base (arguments)
2211                 {
2212                 }
2213
2214                 public override int InferenceScore {
2215                         get {
2216                                 return score;
2217                         }
2218                 }
2219
2220                 public override Type[] InferDelegateArguments (MethodBase method)
2221                 {
2222                         AParametersCollection pd = TypeManager.GetParameterData (method);
2223                         if (arg_count != pd.Count)
2224                                 return null;
2225
2226                         Type[] d_gargs = method.GetGenericArguments ();
2227                         TypeInferenceContext context = new TypeInferenceContext (d_gargs);
2228
2229                         // A lower-bound inference is made from each argument type Uj of D
2230                         // to the corresponding parameter type Tj of M
2231                         for (int i = 0; i < arg_count; ++i) {
2232                                 Type t = pd.Types [i];
2233                                 if (!t.IsGenericParameter)
2234                                         continue;
2235
2236                                 context.LowerBoundInference ((Type)arguments[i], t);
2237                         }
2238
2239                         if (!context.FixAllTypes ())
2240                                 return null;
2241
2242                         return context.InferredTypeArguments;
2243                 }
2244
2245                 public override Type[] InferMethodArguments (EmitContext ec, MethodBase method)
2246                 {
2247                         Type[] method_generic_args = method.GetGenericArguments ();
2248                         TypeInferenceContext context = new TypeInferenceContext (method_generic_args);
2249                         if (!context.UnfixedVariableExists)
2250                                 return Type.EmptyTypes;
2251
2252                         AParametersCollection pd = TypeManager.GetParameterData (method);
2253                         if (!InferInPhases (ec, context, pd))
2254                                 return null;
2255
2256                         return context.InferredTypeArguments;
2257                 }
2258
2259                 //
2260                 // Implements method type arguments inference
2261                 //
2262                 bool InferInPhases (EmitContext ec, TypeInferenceContext tic, AParametersCollection methodParameters)
2263                 {
2264                         int params_arguments_start;
2265                         if (methodParameters.HasParams) {
2266                                 params_arguments_start = methodParameters.Count - 1;
2267                         } else {
2268                                 params_arguments_start = arg_count;
2269                         }
2270
2271                         Type [] ptypes = methodParameters.Types;
2272                         
2273                         //
2274                         // The first inference phase
2275                         //
2276                         Type method_parameter = null;
2277                         for (int i = 0; i < arg_count; i++) {
2278                                 Argument a = (Argument) arguments [i];
2279                                 
2280                                 if (i < params_arguments_start) {
2281                                         method_parameter = methodParameters.Types [i];
2282                                 } else if (i == params_arguments_start) {
2283                                         if (arg_count == params_arguments_start + 1 && TypeManager.HasElementType (a.Type))
2284                                                 method_parameter = methodParameters.Types [params_arguments_start];
2285                                         else
2286                                                 method_parameter = TypeManager.GetElementType (methodParameters.Types [params_arguments_start]);
2287
2288                                         ptypes = (Type[]) ptypes.Clone ();
2289                                         ptypes [i] = method_parameter;
2290                                 }
2291
2292                                 //
2293                                 // When a lambda expression, an anonymous method
2294                                 // is used an explicit argument type inference takes a place
2295                                 //
2296                                 AnonymousMethodExpression am = a.Expr as AnonymousMethodExpression;
2297                                 if (am != null) {
2298                                         if (am.ExplicitTypeInference (tic, method_parameter))
2299                                                 --score; 
2300                                         continue;
2301                                 }
2302
2303                                 if (a.Expr.Type == TypeManager.null_type)
2304                                         continue;
2305
2306                                 //
2307                                 // Otherwise an output type inference is made
2308                                 //
2309                                 score -= tic.OutputTypeInference (ec, a.Expr, method_parameter);
2310                         }
2311
2312                         //
2313                         // Part of the second phase but because it happens only once
2314                         // we don't need to call it in cycle
2315                         //
2316                         bool fixed_any = false;
2317                         if (!tic.FixIndependentTypeArguments (ptypes, ref fixed_any))
2318                                 return false;
2319
2320                         return DoSecondPhase (ec, tic, ptypes, !fixed_any);
2321                 }
2322
2323                 bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, Type[] methodParameters, bool fixDependent)
2324                 {
2325                         bool fixed_any = false;
2326                         if (fixDependent && !tic.FixDependentTypes (ref fixed_any))
2327                                 return false;
2328
2329                         // If no further unfixed type variables exist, type inference succeeds
2330                         if (!tic.UnfixedVariableExists)
2331                                 return true;
2332
2333                         if (!fixed_any && fixDependent)
2334                                 return false;
2335                         
2336                         // For all arguments where the corresponding argument output types
2337                         // contain unfixed type variables but the input types do not,
2338                         // an output type inference is made
2339                         for (int i = 0; i < arg_count; i++) {
2340                                 
2341                                 // Align params arguments
2342                                 Type t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i];
2343                                 
2344                                 if (!TypeManager.IsDelegateType (t_i)) {
2345                                         if (TypeManager.DropGenericTypeArguments (t_i) != TypeManager.expression_type)
2346                                                 continue;
2347
2348                                         t_i = t_i.GetGenericArguments () [0];
2349                                 }
2350
2351                                 MethodInfo mi = Delegate.GetInvokeMethod (t_i, t_i);
2352                                 Type rtype = mi.ReturnType;
2353
2354 #if MS_COMPATIBLE
2355                                 // Blablabla, because reflection does not work with dynamic types
2356                                 Type[] g_args = t_i.GetGenericArguments ();
2357                                 rtype = g_args[rtype.GenericParameterPosition];
2358 #endif
2359
2360                                 if (tic.IsReturnTypeNonDependent (mi, rtype))
2361                                         score -= tic.OutputTypeInference (ec, ((Argument) arguments [i]).Expr, t_i);
2362                         }
2363
2364
2365                         return DoSecondPhase (ec, tic, methodParameters, true);
2366                 }
2367         }
2368
2369         public class TypeInferenceContext
2370         {
2371                 readonly Type[] unfixed_types;
2372                 readonly Type[] fixed_types;
2373                 readonly ArrayList[] bounds;
2374                 bool failed;
2375                 
2376                 public TypeInferenceContext (Type[] typeArguments)
2377                 {
2378                         if (typeArguments.Length == 0)
2379                                 throw new ArgumentException ("Empty generic arguments");
2380
2381                         fixed_types = new Type [typeArguments.Length];
2382                         for (int i = 0; i < typeArguments.Length; ++i) {
2383                                 if (typeArguments [i].IsGenericParameter) {
2384                                         if (bounds == null) {
2385                                                 bounds = new ArrayList [typeArguments.Length];
2386                                                 unfixed_types = new Type [typeArguments.Length];
2387                                         }
2388                                         unfixed_types [i] = typeArguments [i];
2389                                 } else {
2390                                         fixed_types [i] = typeArguments [i];
2391                                 }
2392                         }
2393                 }
2394
2395                 public Type[] InferredTypeArguments {
2396                         get {
2397                                 return fixed_types;
2398                         }
2399                 }
2400
2401                 void AddToBounds (Type t, int index)
2402                 {
2403                         //
2404                         // Some types cannot be used as type arguments
2405                         //
2406                         if (t == TypeManager.void_type || t.IsPointer)
2407                                 return;
2408
2409                         ArrayList a = bounds [index];
2410                         if (a == null) {
2411                                 a = new ArrayList ();
2412                                 bounds [index] = a;
2413                         } else {
2414                                 if (a.Contains (t))
2415                                         return;
2416                         }
2417
2418                         //
2419                         // SPEC: does not cover type inference using constraints
2420                         //
2421                         //if (TypeManager.IsGenericParameter (t)) {
2422                         //    GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
2423                         //    if (constraints != null) {
2424                         //        //if (constraints.EffectiveBaseClass != null)
2425                         //        //    t = constraints.EffectiveBaseClass;
2426                         //    }
2427                         //}
2428                         a.Add (t);
2429                 }
2430                 
2431                 bool AllTypesAreFixed (Type[] types)
2432                 {
2433                         foreach (Type t in types) {
2434                                 if (t.IsGenericParameter) {
2435                                         if (!IsFixed (t))
2436                                                 return false;
2437                                         continue;
2438                                 }
2439
2440                                 if (t.IsGenericType)
2441                                         return AllTypesAreFixed (t.GetGenericArguments ());
2442                         }
2443                         
2444                         return true;
2445                 }               
2446
2447                 //
2448                 // 26.3.3.8 Exact Inference
2449                 //
2450                 public int ExactInference (Type u, Type v)
2451                 {
2452                         // If V is an array type
2453                         if (v.IsArray) {
2454                                 if (!u.IsArray)
2455                                         return 0;
2456
2457                                 if (u.GetArrayRank () != v.GetArrayRank ())
2458                                         return 0;
2459
2460                                 return ExactInference (TypeManager.GetElementType (u), TypeManager.GetElementType (v));
2461                         }
2462
2463                         // If V is constructed type and U is constructed type
2464                         if (v.IsGenericType && !v.IsGenericTypeDefinition) {
2465                                 if (!u.IsGenericType)
2466                                         return 0;
2467
2468                                 Type [] ga_u = u.GetGenericArguments ();
2469                                 Type [] ga_v = v.GetGenericArguments ();
2470                                 if (ga_u.Length != ga_v.Length)
2471                                         return 0;
2472
2473                                 int score = 0;
2474                                 for (int i = 0; i < ga_u.Length; ++i)
2475                                         score += ExactInference (ga_u [i], ga_v [i]);
2476
2477                                 return score > 0 ? 1 : 0;
2478                         }
2479
2480                         // If V is one of the unfixed type arguments
2481                         int pos = IsUnfixed (v);
2482                         if (pos == -1)
2483                                 return 0;
2484
2485                         AddToBounds (u, pos);
2486                         return 1;
2487                 }
2488
2489                 public bool FixAllTypes ()
2490                 {
2491                         for (int i = 0; i < unfixed_types.Length; ++i) {
2492                                 if (!FixType (i))
2493                                         return false;
2494                         }
2495                         return true;
2496                 }
2497
2498                 //
2499                 // All unfixed type variables Xi are fixed for which all of the following hold:
2500                 // a, There is at least one type variable Xj that depends on Xi
2501                 // b, Xi has a non-empty set of bounds
2502                 // 
2503                 public bool FixDependentTypes (ref bool fixed_any)
2504                 {
2505                         for (int i = 0; i < unfixed_types.Length; ++i) {
2506                                 if (unfixed_types[i] == null)
2507                                         continue;
2508
2509                                 if (bounds[i] == null)
2510                                         continue;
2511
2512                                 if (!FixType (i))
2513                                         return false;
2514                                 
2515                                 fixed_any = true;
2516                         }
2517
2518                         return true;
2519                 }
2520
2521                 //
2522                 // All unfixed type variables Xi which depend on no Xj are fixed
2523                 //
2524                 public bool FixIndependentTypeArguments (Type[] methodParameters, ref bool fixed_any)
2525                 {
2526                         ArrayList types_to_fix = new ArrayList (unfixed_types);
2527                         for (int i = 0; i < methodParameters.Length; ++i) {
2528                                 Type t = methodParameters[i];
2529
2530                                 if (!TypeManager.IsDelegateType (t)) {
2531                                         if (TypeManager.DropGenericTypeArguments (t) != TypeManager.expression_type)
2532                                                 continue;
2533
2534                                         t = t.GetGenericArguments () [0];
2535                                 }
2536
2537                                 if (t.IsGenericParameter)
2538                                         continue;
2539
2540                                 MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
2541                                 Type rtype = invoke.ReturnType;
2542                                 if (!rtype.IsGenericParameter && !rtype.IsGenericType)
2543                                         continue;
2544
2545 #if MS_COMPATIBLE
2546                                 // Blablabla, because reflection does not work with dynamic types
2547                                 if (rtype.IsGenericParameter) {
2548                                         Type [] g_args = t.GetGenericArguments ();
2549                                         rtype = g_args [rtype.GenericParameterPosition];
2550                                 }
2551 #endif
2552                                 // Remove dependent types, they cannot be fixed yet
2553                                 RemoveDependentTypes (types_to_fix, rtype);
2554                         }
2555
2556                         foreach (Type t in types_to_fix) {
2557                                 if (t == null)
2558                                         continue;
2559
2560                                 int idx = IsUnfixed (t);
2561                                 if (idx >= 0 && !FixType (idx)) {
2562                                         return false;
2563                                 }
2564                         }
2565
2566                         fixed_any = types_to_fix.Count > 0;
2567                         return true;
2568                 }
2569
2570                 //
2571                 // 26.3.3.10 Fixing
2572                 //
2573                 public bool FixType (int i)
2574                 {
2575                         // It's already fixed
2576                         if (unfixed_types[i] == null)
2577                                 throw new InternalErrorException ("Type argument has been already fixed");
2578
2579                         if (failed)
2580                                 return false;
2581
2582                         ArrayList candidates = (ArrayList)bounds [i];
2583                         if (candidates == null)
2584                                 return false;
2585
2586                         if (candidates.Count == 1) {
2587                                 unfixed_types[i] = null;
2588                                 fixed_types[i] = (Type)candidates[0];
2589                                 return true;
2590                         }
2591
2592                         //
2593                         // Determines a unique type from which there is
2594                         // a standard implicit conversion to all the other
2595                         // candidate types.
2596                         //
2597                         Type best_candidate = null;
2598                         int cii;
2599                         int candidates_count = candidates.Count;
2600                         for (int ci = 0; ci < candidates_count; ++ci) {
2601                                 Type candidate = (Type)candidates [ci];
2602                                 for (cii = 0; cii < candidates_count; ++cii) {
2603                                         if (cii == ci)
2604                                                 continue;
2605
2606                                         if (!Convert.ImplicitConversionExists (null,
2607                                                 new TypeExpression ((Type)candidates [cii], Location.Null), candidate)) {
2608                                                 break;
2609                                         }
2610                                 }
2611
2612                                 if (cii != candidates_count)
2613                                         continue;
2614
2615                                 if (best_candidate != null)
2616                                         return false;
2617
2618                                 best_candidate = candidate;
2619                         }
2620
2621                         if (best_candidate == null)
2622                                 return false;
2623
2624                         unfixed_types[i] = null;
2625                         fixed_types[i] = best_candidate;
2626                         return true;
2627                 }
2628                 
2629                 //
2630                 // Uses inferred types to inflate delegate type argument
2631                 //
2632                 public Type InflateGenericArgument (Type parameter)
2633                 {
2634                         if (parameter.IsGenericParameter) {
2635                                 //
2636                                 // Inflate method generic argument (MVAR) only
2637                                 //
2638                                 if (parameter.DeclaringMethod == null)
2639                                         return parameter;
2640
2641                                 return fixed_types [parameter.GenericParameterPosition];
2642                         }
2643
2644                         if (parameter.IsGenericType) {
2645                                 Type [] parameter_targs = parameter.GetGenericArguments ();
2646                                 for (int ii = 0; ii < parameter_targs.Length; ++ii) {
2647                                         parameter_targs [ii] = InflateGenericArgument (parameter_targs [ii]);
2648                                 }
2649                                 return parameter.GetGenericTypeDefinition ().MakeGenericType (parameter_targs);
2650                         }
2651
2652                         return parameter;
2653                 }
2654                 
2655                 //
2656                 // Tests whether all delegate input arguments are fixed and generic output type
2657                 // requires output type inference 
2658                 //
2659                 public bool IsReturnTypeNonDependent (MethodInfo invoke, Type returnType)
2660                 {
2661                         if (returnType.IsGenericParameter) {
2662                                 if (IsFixed (returnType))
2663                                     return false;
2664                         } else if (returnType.IsGenericType) {
2665                                 if (TypeManager.IsDelegateType (returnType)) {
2666                                         invoke = Delegate.GetInvokeMethod (returnType, returnType);
2667                                         return IsReturnTypeNonDependent (invoke, invoke.ReturnType);
2668                                 }
2669                                         
2670                                 Type[] g_args = returnType.GetGenericArguments ();
2671                                 
2672                                 // At least one unfixed return type has to exist 
2673                                 if (AllTypesAreFixed (g_args))
2674                                         return false;
2675                         } else {
2676                                 return false;
2677                         }
2678
2679                         // All generic input arguments have to be fixed
2680                         AParametersCollection d_parameters = TypeManager.GetParameterData (invoke);
2681                         return AllTypesAreFixed (d_parameters.Types);
2682                 }
2683                 
2684                 bool IsFixed (Type type)
2685                 {
2686                         return IsUnfixed (type) == -1;
2687                 }               
2688
2689                 int IsUnfixed (Type type)
2690                 {
2691                         if (!type.IsGenericParameter)
2692                                 return -1;
2693
2694                         //return unfixed_types[type.GenericParameterPosition] != null;
2695                         for (int i = 0; i < unfixed_types.Length; ++i) {
2696                                 if (unfixed_types [i] == type)
2697                                         return i;
2698                         }
2699
2700                         return -1;
2701                 }
2702
2703                 //
2704                 // 26.3.3.9 Lower-bound Inference
2705                 //
2706                 public int LowerBoundInference (Type u, Type v)
2707                 {
2708                         // If V is one of the unfixed type arguments
2709                         int pos = IsUnfixed (v);
2710                         if (pos != -1) {
2711                                 AddToBounds (u, pos);
2712                                 return 1;
2713                         }                       
2714
2715                         // If U is an array type
2716                         if (u.IsArray) {
2717                                 int u_dim = u.GetArrayRank ();
2718                                 Type v_e;
2719                                 Type u_e = TypeManager.GetElementType (u);
2720
2721                                 if (v.IsArray) {
2722                                         if (u_dim != v.GetArrayRank ())
2723                                                 return 0;
2724
2725                                         v_e = TypeManager.GetElementType (v);
2726
2727                                         if (u.IsByRef) {
2728                                                 return LowerBoundInference (u_e, v_e);
2729                                         }
2730
2731                                         return ExactInference (u_e, v_e);
2732                                 }
2733
2734                                 if (u_dim != 1)
2735                                         return 0;
2736
2737                                 if (v.IsGenericType) {
2738                                         Type g_v = v.GetGenericTypeDefinition ();
2739                                         if ((g_v != TypeManager.generic_ilist_type) && (g_v != TypeManager.generic_icollection_type) &&
2740                                                 (g_v != TypeManager.generic_ienumerable_type))
2741                                                 return 0;
2742
2743                                         v_e = TypeManager.GetTypeArguments (v)[0];
2744
2745                                         if (u.IsByRef) {
2746                                                 return LowerBoundInference (u_e, v_e);
2747                                         }
2748
2749                                         return ExactInference (u_e, v_e);
2750                                 }
2751                         } else if (v.IsGenericType && !v.IsGenericTypeDefinition) {
2752                                 //
2753                                 // if V is a constructed type C<V1..Vk> and there is a unique set of types U1..Uk
2754                                 // such that a standard implicit conversion exists from U to C<U1..Uk> then an exact
2755                                 // inference is made from each Ui for the corresponding Vi
2756                                 //
2757                                 ArrayList u_candidates = new ArrayList ();
2758                                 if (u.IsGenericType)
2759                                         u_candidates.Add (u);
2760
2761                                 for (Type t = u.BaseType; t != null; t = t.BaseType) {
2762                                         if (t.IsGenericType && !t.IsGenericTypeDefinition)
2763                                                 u_candidates.Add (t);
2764                                 }
2765
2766                                 // TODO: Implement GetGenericInterfaces only and remove
2767                                 // the if from foreach
2768                                 u_candidates.AddRange (TypeManager.GetInterfaces (u));
2769
2770                                 Type open_v = v.GetGenericTypeDefinition ();
2771                                 Type [] unique_candidate_targs = null;
2772                                 Type [] ga_v = v.GetGenericArguments ();                        
2773                                 foreach (Type u_candidate in u_candidates) {
2774                                         if (!u_candidate.IsGenericType || u_candidate.IsGenericTypeDefinition)
2775                                                 continue;
2776
2777                                         if (TypeManager.DropGenericTypeArguments (u_candidate) != open_v)
2778                                                 continue;
2779
2780                                         //
2781                                         // The unique set of types U1..Uk means that if we have an interface C<T>,
2782                                         // class U: C<int>, C<long> then no type inference is made when inferring
2783                                         // from U to C<T> because T could be int or long
2784                                         //
2785                                         if (unique_candidate_targs != null) {
2786                                                 Type[] second_unique_candidate_targs = u_candidate.GetGenericArguments ();
2787                                                 if (TypeManager.IsEqual (unique_candidate_targs, second_unique_candidate_targs)) {
2788                                                         unique_candidate_targs = second_unique_candidate_targs;
2789                                                         continue;
2790                                                 }
2791                                                 
2792                                                 //
2793                                                 // This should always cause type inference failure
2794                                                 //
2795                                                 failed = true;
2796                                                 return 1;
2797                                         }
2798
2799                                         unique_candidate_targs = u_candidate.GetGenericArguments ();
2800                                 }
2801
2802                                 if (unique_candidate_targs != null) {
2803                                         int score = 0;
2804                                         for (int i = 0; i < unique_candidate_targs.Length; ++i)
2805                                                 if (ExactInference (unique_candidate_targs [i], ga_v [i]) == 0)
2806                                                         ++score;
2807                                         return score;
2808                                 }
2809                         }
2810
2811                         return 0;
2812                 }
2813
2814                 //
2815                 // 26.3.3.6 Output Type Inference
2816                 //
2817                 public int OutputTypeInference (EmitContext ec, Expression e, Type t)
2818                 {
2819                         // If e is a lambda or anonymous method with inferred return type
2820                         AnonymousMethodExpression ame = e as AnonymousMethodExpression;
2821                         if (ame != null) {
2822                                 Type rt = ame.InferReturnType (ec, this, t);
2823                                 MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
2824
2825                                 if (rt == null) {
2826                                         AParametersCollection pd = TypeManager.GetParameterData (invoke);
2827                                         return ame.Parameters.Count == pd.Count ? 1 : 0;
2828                                 }
2829
2830                                 Type rtype = invoke.ReturnType;
2831 #if MS_COMPATIBLE
2832                                 // Blablabla, because reflection does not work with dynamic types
2833                                 Type [] g_args = t.GetGenericArguments ();
2834                                 rtype = g_args [rtype.GenericParameterPosition];
2835 #endif
2836                                 return LowerBoundInference (rt, rtype) + 1;
2837                         }
2838
2839                         //
2840                         // if E is a method group and T is a delegate type or expression tree type
2841                         // return type Tb with parameter types T1..Tk and return type Tb, and overload
2842                         // resolution of E with the types T1..Tk yields a single method with return type U,
2843                         // then a lower-bound inference is made from U for Tb.
2844                         //
2845                         if (e is MethodGroupExpr) {
2846                                 // TODO: Or expression tree
2847                                 if (!TypeManager.IsDelegateType (t))
2848                                         return 0;
2849
2850                                 MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
2851                                 Type rtype = invoke.ReturnType;
2852 #if MS_COMPATIBLE
2853                                 // Blablabla, because reflection does not work with dynamic types
2854                                 Type [] g_args = t.GetGenericArguments ();
2855                                 rtype = g_args [rtype.GenericParameterPosition];
2856 #endif
2857
2858                                 if (!TypeManager.IsGenericType (rtype))
2859                                         return 0;
2860
2861                                 MethodGroupExpr mg = (MethodGroupExpr) e;
2862                                 ArrayList args = DelegateCreation.CreateDelegateMethodArguments (invoke, e.Location);
2863                                 mg = mg.OverloadResolve (ec, ref args, true, e.Location);
2864                                 if (mg == null)
2865                                         return 0;
2866
2867                                 // TODO: What should happen when return type is of generic type ?
2868                                 throw new NotImplementedException ();
2869 //                              return LowerBoundInference (null, rtype) + 1;
2870                         }
2871
2872                         //
2873                         // if e is an expression with type U, then
2874                         // a lower-bound inference is made from U for T
2875                         //
2876                         return LowerBoundInference (e.Type, t) * 2;
2877                 }
2878
2879                 void RemoveDependentTypes (ArrayList types, Type returnType)
2880                 {
2881                         int idx = IsUnfixed (returnType);
2882                         if (idx >= 0) {
2883                                 types [idx] = null;
2884                                 return;
2885                         }
2886
2887                         if (returnType.IsGenericType) {
2888                                 foreach (Type t in returnType.GetGenericArguments ()) {
2889                                         RemoveDependentTypes (types, t);
2890                                 }
2891                         }
2892                 }
2893
2894                 public bool UnfixedVariableExists {
2895                         get {
2896                                 if (unfixed_types == null)
2897                                         return false;
2898
2899                                 foreach (Type ut in unfixed_types)
2900                                         if (ut != null)
2901                                                 return true;
2902                                 return false;
2903                         }
2904                 }
2905         }
2906 }