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