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