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