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