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