692ee082f433cd1774ce10532f77ddabb1723317
[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 void InflateConstraints (Type declaring)
914                 {
915                         if (constraints != null)
916                                 gc = new InflatedConstraints (constraints, declaring);
917                 }
918                 
919                 public override bool IsClsComplianceRequired ()
920                 {
921                         return false;
922                 }
923
924                 protected class InflatedConstraints : GenericConstraints
925                 {
926                         GenericConstraints gc;
927                         Type base_type;
928                         Type class_constraint;
929                         Type[] iface_constraints;
930                         Type[] dargs;
931
932                         public InflatedConstraints (GenericConstraints gc, Type declaring)
933                                 : this (gc, TypeManager.GetTypeArguments (declaring))
934                         { }
935
936                         public InflatedConstraints (GenericConstraints gc, Type[] dargs)
937                         {
938                                 this.gc = gc;
939                                 this.dargs = dargs;
940
941                                 ArrayList list = new ArrayList ();
942                                 if (gc.HasClassConstraint)
943                                         list.Add (inflate (gc.ClassConstraint));
944                                 foreach (Type iface in gc.InterfaceConstraints)
945                                         list.Add (inflate (iface));
946
947                                 bool has_class_constr = false;
948                                 if (list.Count > 0) {
949                                         Type first = (Type) list [0];
950                                         has_class_constr = !first.IsGenericParameter && !first.IsInterface;
951                                 }
952
953                                 if ((list.Count > 0) && has_class_constr) {
954                                         class_constraint = (Type) list [0];
955                                         iface_constraints = new Type [list.Count - 1];
956                                         list.CopyTo (1, iface_constraints, 0, list.Count - 1);
957                                 } else {
958                                         iface_constraints = new Type [list.Count];
959                                         list.CopyTo (iface_constraints, 0);
960                                 }
961
962                                 if (HasValueTypeConstraint)
963                                         base_type = TypeManager.value_type;
964                                 else if (class_constraint != null)
965                                         base_type = class_constraint;
966                                 else
967                                         base_type = TypeManager.object_type;
968                         }
969
970                         Type inflate (Type t)
971                         {
972                                 if (t == null)
973                                         return null;
974                                 if (t.IsGenericParameter)
975                                         return t.GenericParameterPosition < dargs.Length ? dargs [t.GenericParameterPosition] : t;
976                                 if (t.IsGenericType) {
977                                         Type[] args = t.GetGenericArguments ();
978                                         Type[] inflated = new Type [args.Length];
979
980                                         for (int i = 0; i < args.Length; i++)
981                                                 inflated [i] = inflate (args [i]);
982
983                                         t = t.GetGenericTypeDefinition ();
984                                         t = t.MakeGenericType (inflated);
985                                 }
986
987                                 return t;
988                         }
989
990                         public override string TypeParameter {
991                                 get { return gc.TypeParameter; }
992                         }
993
994                         public override GenericParameterAttributes Attributes {
995                                 get { return gc.Attributes; }
996                         }
997
998                         public override Type ClassConstraint {
999                                 get { return class_constraint; }
1000                         }
1001
1002                         public override Type EffectiveBaseClass {
1003                                 get { return base_type; }
1004                         }
1005
1006                         public override Type[] InterfaceConstraints {
1007                                 get { return iface_constraints; }
1008                         }
1009                 }
1010         }
1011
1012         /// <summary>
1013         ///   A TypeExpr which already resolved to a type parameter.
1014         /// </summary>
1015         public class TypeParameterExpr : TypeExpr {
1016                 TypeParameter type_parameter;
1017
1018                 public TypeParameter TypeParameter {
1019                         get {
1020                                 return type_parameter;
1021                         }
1022                 }
1023                 
1024                 public TypeParameterExpr (TypeParameter type_parameter, Location loc)
1025                 {
1026                         this.type_parameter = type_parameter;
1027                         this.loc = loc;
1028                 }
1029
1030                 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
1031                 {
1032                         throw new NotSupportedException ();
1033                 }
1034
1035                 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
1036                 {
1037                         type = type_parameter.Type;
1038                         eclass = ExprClass.TypeParameter;
1039                         return this;
1040                 }
1041
1042                 public override bool IsInterface {
1043                         get { return false; }
1044                 }
1045
1046                 public override bool CheckAccessLevel (DeclSpace ds)
1047                 {
1048                         return true;
1049                 }
1050         }
1051
1052         //
1053         // Tracks the type arguments when instantiating a generic type. It's used
1054         // by both type arguments and type parameters
1055         //
1056         public class TypeArguments {
1057                 ArrayList args;
1058                 Type[] atypes;
1059                 
1060                 public TypeArguments ()
1061                 {
1062                         args = new ArrayList ();
1063                 }
1064
1065                 public TypeArguments (params FullNamedExpression[] types)
1066                 {
1067                         this.args = new ArrayList (types);
1068                 }
1069
1070                 public void Add (FullNamedExpression type)
1071                 {
1072                         args.Add (type);
1073                 }
1074
1075                 public void Add (TypeArguments new_args)
1076                 {
1077                         args.AddRange (new_args.args);
1078                 }
1079
1080                 // TODO: Should be deleted
1081                 public TypeParameterName[] GetDeclarations ()
1082                 {
1083                         return (TypeParameterName[]) args.ToArray (typeof (TypeParameterName));
1084                 }
1085
1086                 /// <summary>
1087                 ///   We may only be used after Resolve() is called and return the fully
1088                 ///   resolved types.
1089                 /// </summary>
1090                 public Type[] Arguments {
1091                         get {
1092                                 return atypes;
1093                         }
1094                 }
1095
1096                 public int Count {
1097                         get {
1098                                 return args.Count;
1099                         }
1100                 }
1101
1102                 public string GetSignatureForError()
1103                 {
1104                         StringBuilder sb = new StringBuilder();
1105                         for (int i = 0; i < Count; ++i)
1106                         {
1107                                 Expression expr = (Expression)args [i];
1108                                 sb.Append(expr.GetSignatureForError());
1109                                 if (i + 1 < Count)
1110                                         sb.Append(',');
1111                         }
1112                         return sb.ToString();
1113                 }
1114
1115                 /// <summary>
1116                 ///   Resolve the type arguments.
1117                 /// </summary>
1118                 public bool Resolve (IResolveContext ec)
1119                 {
1120                         if (atypes != null)
1121                                 return atypes.Length != 0;
1122
1123                         int count = args.Count;
1124                         bool ok = true;
1125
1126                         atypes = new Type [count];
1127
1128                         for (int i = 0; i < count; i++){
1129                                 TypeExpr te = ((FullNamedExpression) args[i]).ResolveAsTypeTerminal (ec, false);
1130                                 if (te == null) {
1131                                         ok = false;
1132                                         continue;
1133                                 }
1134
1135                                 atypes[i] = te.Type;
1136
1137                                 if (te.Type.IsSealed && te.Type.IsAbstract) {
1138                                         Report.Error (718, te.Location, "`{0}': static classes cannot be used as generic arguments",
1139                                                 te.GetSignatureForError ());
1140                                         ok = false;
1141                                 }
1142
1143                                 if (te.Type.IsPointer || TypeManager.IsSpecialType (te.Type)) {
1144                                         Report.Error (306, te.Location,
1145                                                 "The type `{0}' may not be used as a type argument",
1146                                                 te.GetSignatureForError ());
1147                                         ok = false;
1148                                 }
1149                         }
1150
1151                         if (!ok)
1152                                 atypes = Type.EmptyTypes;
1153
1154                         return ok;
1155                 }
1156
1157                 public TypeArguments Clone ()
1158                 {
1159                         TypeArguments copy = new TypeArguments ();
1160                         foreach (Expression ta in args)
1161                                 copy.args.Add (ta);
1162
1163                         return copy;
1164                 }
1165         }
1166
1167         public class TypeParameterName : SimpleName
1168         {
1169                 Attributes attributes;
1170
1171                 public TypeParameterName (string name, Attributes attrs, Location loc)
1172                         : base (name, loc)
1173                 {
1174                         attributes = attrs;
1175                 }
1176
1177                 public Attributes OptAttributes {
1178                         get {
1179                                 return attributes;
1180                         }
1181                 }
1182         }
1183
1184         /// <summary>
1185         ///   A reference expression to generic type
1186         /// </summary>  
1187         class GenericTypeExpr : TypeExpr
1188         {
1189                 TypeArguments args;
1190                 Type[] gen_params;      // TODO: Waiting for constrains check cleanup
1191                 Type open_type;
1192
1193                 //
1194                 // Should be carefully used only with defined generic containers. Type parameters
1195                 // can be used as type arguments in this case.
1196                 //
1197                 // TODO: This could be GenericTypeExpr specialization
1198                 //
1199                 public GenericTypeExpr (DeclSpace gType, Location l)
1200                 {
1201                         open_type = gType.TypeBuilder.GetGenericTypeDefinition ();
1202
1203                         args = new TypeArguments ();
1204                         foreach (TypeParameter type_param in gType.TypeParameters)
1205                                 args.Add (new TypeParameterExpr (type_param, l));
1206
1207                         this.loc = l;
1208                 }
1209
1210                 /// <summary>
1211                 ///   Instantiate the generic type `t' with the type arguments `args'.
1212                 ///   Use this constructor if you already know the fully resolved
1213                 ///   generic type.
1214                 /// </summary>          
1215                 public GenericTypeExpr (Type t, TypeArguments args, Location l)
1216                 {
1217                         open_type = t.GetGenericTypeDefinition ();
1218
1219                         loc = l;
1220                         this.args = args;
1221                 }
1222
1223                 public TypeArguments TypeArguments {
1224                         get { return args; }
1225                 }
1226
1227                 public override string GetSignatureForError ()
1228                 {
1229                         return TypeManager.CSharpName (type);
1230                 }
1231
1232                 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
1233                 {
1234                         if (eclass != ExprClass.Invalid)
1235                                 return this;
1236
1237                         eclass = ExprClass.Type;
1238
1239                         if (!args.Resolve (ec))
1240                                 return null;
1241
1242                         gen_params = open_type.GetGenericArguments ();
1243                         Type[] atypes = args.Arguments;
1244                         
1245                         if (atypes.Length != gen_params.Length) {
1246                                 Namespace.Error_InvalidNumberOfTypeArguments (open_type, loc);
1247                                 return null;
1248                         }
1249
1250                         //
1251                         // Now bind the parameters
1252                         //
1253                         type = open_type.MakeGenericType (atypes);
1254                         return this;
1255                 }
1256
1257                 /// <summary>
1258                 ///   Check the constraints; we're called from ResolveAsTypeTerminal()
1259                 ///   after fully resolving the constructed type.
1260                 /// </summary>
1261                 public bool CheckConstraints (IResolveContext ec)
1262                 {
1263                         return ConstraintChecker.CheckConstraints (ec, open_type, gen_params, args.Arguments, loc);
1264                 }
1265
1266                 public override bool CheckAccessLevel (DeclSpace ds)
1267                 {
1268                         return ds.CheckAccessLevel (open_type);
1269                 }
1270
1271                 public override bool AsAccessible (DeclSpace ds)
1272                 {
1273                         foreach (Type t in args.Arguments) {
1274                                 if (!ds.IsAccessibleAs (t))
1275                                         return false;
1276                         }
1277
1278                         return ds.IsAccessibleAs (open_type);
1279                 }
1280
1281                 public override bool IsClass {
1282                         get { return open_type.IsClass; }
1283                 }
1284
1285                 public override bool IsValueType {
1286                         get { return TypeManager.IsStruct (open_type); }
1287                 }
1288
1289                 public override bool IsInterface {
1290                         get { return open_type.IsInterface; }
1291                 }
1292
1293                 public override bool IsSealed {
1294                         get { return open_type.IsSealed; }
1295                 }
1296
1297                 public override bool Equals (object obj)
1298                 {
1299                         GenericTypeExpr cobj = obj as GenericTypeExpr;
1300                         if (cobj == null)
1301                                 return false;
1302
1303                         if ((type == null) || (cobj.type == null))
1304                                 return false;
1305
1306                         return type == cobj.type;
1307                 }
1308
1309                 public override int GetHashCode ()
1310                 {
1311                         return base.GetHashCode ();
1312                 }
1313         }
1314
1315         public abstract class ConstraintChecker
1316         {
1317                 protected readonly Type[] gen_params;
1318                 protected readonly Type[] atypes;
1319                 protected readonly Location loc;
1320
1321                 protected ConstraintChecker (Type[] gen_params, Type[] atypes, Location loc)
1322                 {
1323                         this.gen_params = gen_params;
1324                         this.atypes = atypes;
1325                         this.loc = loc;
1326                 }
1327
1328                 /// <summary>
1329                 ///   Check the constraints; we're called from ResolveAsTypeTerminal()
1330                 ///   after fully resolving the constructed type.
1331                 /// </summary>
1332                 public bool CheckConstraints (IResolveContext ec)
1333                 {
1334                         for (int i = 0; i < gen_params.Length; i++) {
1335                                 if (!CheckConstraints (ec, i))
1336                                         return false;
1337                         }
1338
1339                         return true;
1340                 }
1341
1342                 protected bool CheckConstraints (IResolveContext ec, int index)
1343                 {
1344                         Type atype = atypes [index];
1345                         Type ptype = gen_params [index];
1346
1347                         if (atype == ptype)
1348                                 return true;
1349
1350                         Expression aexpr = new EmptyExpression (atype);
1351
1352                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (ptype);
1353                         if (gc == null)
1354                                 return true;
1355
1356                         bool is_class, is_struct;
1357                         if (atype.IsGenericParameter) {
1358                                 GenericConstraints agc = TypeManager.GetTypeParameterConstraints (atype);
1359                                 if (agc != null) {
1360                                         if (agc is Constraints)
1361                                                 ((Constraints) agc).Resolve (ec);
1362                                         is_class = agc.IsReferenceType;
1363                                         is_struct = agc.IsValueType;
1364                                 } else {
1365                                         is_class = is_struct = false;
1366                                 }
1367                         } else {
1368 #if MS_COMPATIBLE
1369                                 is_class = false;
1370                                 if (!atype.IsGenericType)
1371 #endif
1372                                 is_class = atype.IsClass || atype.IsInterface;
1373                                 is_struct = TypeManager.IsValueType (atype) && !TypeManager.IsNullableType (atype);
1374                         }
1375
1376                         //
1377                         // First, check the `class' and `struct' constraints.
1378                         //
1379                         if (gc.HasReferenceTypeConstraint && !is_class) {
1380                                 Report.Error (452, loc, "The type `{0}' must be " +
1381                                               "a reference type in order to use it " +
1382                                               "as type parameter `{1}' in the " +
1383                                               "generic type or method `{2}'.",
1384                                               TypeManager.CSharpName (atype),
1385                                               TypeManager.CSharpName (ptype),
1386                                               GetSignatureForError ());
1387                                 return false;
1388                         } else if (gc.HasValueTypeConstraint && !is_struct) {
1389                                 Report.Error (453, loc, "The type `{0}' must be a " +
1390                                               "non-nullable value type in order to use it " +
1391                                               "as type parameter `{1}' in the " +
1392                                               "generic type or method `{2}'.",
1393                                               TypeManager.CSharpName (atype),
1394                                               TypeManager.CSharpName (ptype),
1395                                               GetSignatureForError ());
1396                                 return false;
1397                         }
1398
1399                         //
1400                         // The class constraint comes next.
1401                         //
1402                         if (gc.HasClassConstraint) {
1403                                 if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint))
1404                                         return false;
1405                         }
1406
1407                         //
1408                         // Now, check the interface constraints.
1409                         //
1410                         if (gc.InterfaceConstraints != null) {
1411                                 foreach (Type it in gc.InterfaceConstraints) {
1412                                         if (!CheckConstraint (ec, ptype, aexpr, it))
1413                                                 return false;
1414                                 }
1415                         }
1416
1417                         //
1418                         // Finally, check the constructor constraint.
1419                         //
1420
1421                         if (!gc.HasConstructorConstraint)
1422                                 return true;
1423
1424                         if (TypeManager.IsBuiltinType (atype) || TypeManager.IsValueType (atype))
1425                                 return true;
1426
1427                         if (HasDefaultConstructor (atype))
1428                                 return true;
1429
1430                         Report_SymbolRelatedToPreviousError ();
1431                         Report.SymbolRelatedToPreviousError (atype);
1432                         Report.Error (310, loc, "The type `{0}' must have a public " +
1433                                       "parameterless constructor in order to use it " +
1434                                       "as parameter `{1}' in the generic type or " +
1435                                       "method `{2}'",
1436                                       TypeManager.CSharpName (atype),
1437                                       TypeManager.CSharpName (ptype),
1438                                       GetSignatureForError ());
1439                         return false;
1440                 }
1441
1442                 protected bool CheckConstraint (IResolveContext ec, Type ptype, Expression expr,
1443                                                 Type ctype)
1444                 {
1445                         if (TypeManager.HasGenericArguments (ctype)) {
1446                                 Type[] types = TypeManager.GetTypeArguments (ctype);
1447
1448                                 TypeArguments new_args = new TypeArguments ();
1449
1450                                 for (int i = 0; i < types.Length; i++) {
1451                                         Type t = types [i];
1452
1453                                         if (t.IsGenericParameter) {
1454                                                 int pos = t.GenericParameterPosition;
1455                                                 t = atypes [pos];
1456                                         }
1457                                         new_args.Add (new TypeExpression (t, loc));
1458                                 }
1459
1460                                 TypeExpr ct = new GenericTypeExpr (ctype, new_args, loc);
1461                                 if (ct.ResolveAsTypeStep (ec, false) == null)
1462                                         return false;
1463                                 ctype = ct.Type;
1464                         } else if (ctype.IsGenericParameter) {
1465                                 int pos = ctype.GenericParameterPosition;
1466                                 if (ctype.DeclaringMethod == null) {
1467                                         // FIXME: Implement
1468                                         return true;
1469                                 } else {                                
1470                                         ctype = atypes [pos];
1471                                 }
1472                         }
1473
1474                         if (Convert.ImplicitStandardConversionExists (expr, ctype))
1475                                 return true;
1476
1477                         Report_SymbolRelatedToPreviousError ();
1478                         Report.SymbolRelatedToPreviousError (expr.Type);
1479
1480                         if (TypeManager.IsNullableType (expr.Type) && ctype.IsInterface) {
1481                                 Report.Error (313, loc,
1482                                         "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. " +
1483                                         "The nullable type `{0}' never satisfies interface constraint of type `{3}'",
1484                                         TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ptype),
1485                                         GetSignatureForError (), TypeManager.CSharpName (ctype));
1486                         } else {
1487                                 Report.Error (309, loc,
1488                                         "The type `{0}' must be convertible to `{1}' in order to " +
1489                                         "use it as parameter `{2}' in the generic type or method `{3}'",
1490                                         TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ctype),
1491                                         TypeManager.CSharpName (ptype), GetSignatureForError ());
1492                         }
1493                         return false;
1494                 }
1495
1496                 static bool HasDefaultConstructor (Type atype)
1497                 {
1498                         TypeParameter tparam = TypeManager.LookupTypeParameter (atype);
1499                         if (tparam != null) {
1500                                 if (tparam.GenericConstraints == null)
1501                                         return false;
1502                                                 
1503                                 return tparam.GenericConstraints.HasConstructorConstraint || 
1504                                         tparam.GenericConstraints.HasValueTypeConstraint;
1505                         }
1506                 
1507                         if (atype.IsAbstract)
1508                                 return false;
1509
1510                 again:
1511                         atype = TypeManager.DropGenericTypeArguments (atype);
1512                         if (atype is TypeBuilder) {
1513                                 TypeContainer tc = TypeManager.LookupTypeContainer (atype);
1514                                 if (tc.InstanceConstructors == null) {
1515                                         atype = atype.BaseType;
1516                                         goto again;
1517                                 }
1518
1519                                 foreach (Constructor c in tc.InstanceConstructors) {
1520                                         if ((c.ModFlags & Modifiers.PUBLIC) == 0)
1521                                                 continue;
1522                                         if ((c.Parameters.FixedParameters != null) &&
1523                                             (c.Parameters.FixedParameters.Length != 0))
1524                                                 continue;
1525                                         if (c.Parameters.HasArglist || c.Parameters.HasParams)
1526                                                 continue;
1527
1528                                         return true;
1529                                 }
1530                         }
1531
1532                         MemberInfo [] list = TypeManager.MemberLookup (null, null, atype, MemberTypes.Constructor,
1533                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
1534                                 ConstructorInfo.ConstructorName, null);
1535
1536                         if (list == null)
1537                                 return false;
1538
1539                         foreach (MethodBase mb in list) {
1540                                 AParametersCollection pd = TypeManager.GetParameterData (mb);
1541                                 if (pd.Count == 0)
1542                                         return true;
1543                         }
1544
1545                         return false;
1546                 }
1547
1548                 protected abstract string GetSignatureForError ();
1549                 protected abstract void Report_SymbolRelatedToPreviousError ();
1550
1551                 public static bool CheckConstraints (EmitContext ec, MethodBase definition,
1552                                                      MethodBase instantiated, Location loc)
1553                 {
1554                         MethodConstraintChecker checker = new MethodConstraintChecker (
1555                                 definition, definition.GetGenericArguments (),
1556                                 instantiated.GetGenericArguments (), loc);
1557
1558                         return checker.CheckConstraints (ec);
1559                 }
1560
1561                 public static bool CheckConstraints (IResolveContext ec, Type gt, Type[] gen_params,
1562                                                      Type[] atypes, Location loc)
1563                 {
1564                         TypeConstraintChecker checker = new TypeConstraintChecker (
1565                                 gt, gen_params, atypes, loc);
1566
1567                         return checker.CheckConstraints (ec);
1568                 }
1569
1570                 protected class MethodConstraintChecker : ConstraintChecker
1571                 {
1572                         MethodBase definition;
1573
1574                         public MethodConstraintChecker (MethodBase definition, Type[] gen_params,
1575                                                         Type[] atypes, Location loc)
1576                                 : base (gen_params, atypes, loc)
1577                         {
1578                                 this.definition = definition;
1579                         }
1580
1581                         protected override string GetSignatureForError ()
1582                         {
1583                                 return TypeManager.CSharpSignature (definition);
1584                         }
1585
1586                         protected override void Report_SymbolRelatedToPreviousError ()
1587                         {
1588                                 Report.SymbolRelatedToPreviousError (definition);
1589                         }
1590                 }
1591
1592                 protected class TypeConstraintChecker : ConstraintChecker
1593                 {
1594                         Type gt;
1595
1596                         public TypeConstraintChecker (Type gt, Type[] gen_params, Type[] atypes,
1597                                                       Location loc)
1598                                 : base (gen_params, atypes, loc)
1599                         {
1600                                 this.gt = gt;
1601                         }
1602
1603                         protected override string GetSignatureForError ()
1604                         {
1605                                 return TypeManager.CSharpName (gt);
1606                         }
1607
1608                         protected override void Report_SymbolRelatedToPreviousError ()
1609                         {
1610                                 Report.SymbolRelatedToPreviousError (gt);
1611                         }
1612                 }
1613         }
1614
1615         /// <summary>
1616         ///   A generic method definition.
1617         /// </summary>
1618         public class GenericMethod : DeclSpace
1619         {
1620                 FullNamedExpression return_type;
1621                 Parameters parameters;
1622
1623                 public GenericMethod (NamespaceEntry ns, DeclSpace parent, MemberName name,
1624                                       FullNamedExpression return_type, Parameters parameters)
1625                         : base (ns, parent, name, null)
1626                 {
1627                         this.return_type = return_type;
1628                         this.parameters = parameters;
1629                 }
1630
1631                 public override TypeBuilder DefineType ()
1632                 {
1633                         throw new Exception ();
1634                 }
1635
1636                 public override bool Define ()
1637                 {
1638                         for (int i = 0; i < TypeParameters.Length; i++)
1639                                 if (!TypeParameters [i].Resolve (this))
1640                                         return false;
1641
1642                         return true;
1643                 }
1644
1645                 /// <summary>
1646                 ///   Define and resolve the type parameters.
1647                 ///   We're called from Method.Define().
1648                 /// </summary>
1649                 public bool Define (MethodOrOperator m)
1650                 {
1651                         TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
1652                         string[] snames = new string [names.Length];
1653                         for (int i = 0; i < names.Length; i++) {
1654                                 string type_argument_name = names[i].Name;
1655                                 int idx = parameters.GetParameterIndexByName (type_argument_name);
1656                                 if (idx >= 0) {
1657                                         Block b = m.Block;
1658                                         if (b == null)
1659                                                 b = new Block (null);
1660
1661                                         b.Error_AlreadyDeclaredTypeParameter (parameters [i].Location,
1662                                                 type_argument_name, "method parameter");
1663                                 }
1664                                 
1665                                 snames[i] = type_argument_name;
1666                         }
1667
1668                         GenericTypeParameterBuilder[] gen_params = m.MethodBuilder.DefineGenericParameters (snames);
1669                         for (int i = 0; i < TypeParameters.Length; i++)
1670                                 TypeParameters [i].Define (gen_params [i]);
1671
1672                         if (!Define ())
1673                                 return false;
1674
1675                         for (int i = 0; i < TypeParameters.Length; i++) {
1676                                 if (!TypeParameters [i].ResolveType (this))
1677                                         return false;
1678                         }
1679
1680                         return true;
1681                 }
1682
1683                 /// <summary>
1684                 ///   We're called from MethodData.Define() after creating the MethodBuilder.
1685                 /// </summary>
1686                 public bool DefineType (EmitContext ec, MethodBuilder mb,
1687                                         MethodInfo implementing, bool is_override)
1688                 {
1689                         for (int i = 0; i < TypeParameters.Length; i++)
1690                                 if (!TypeParameters [i].DefineType (
1691                                             ec, mb, implementing, is_override))
1692                                         return false;
1693
1694                         bool ok = parameters.Resolve (ec);
1695
1696                         if ((return_type != null) && (return_type.ResolveAsTypeTerminal (ec, false) == null))
1697                                 ok = false;
1698
1699                         return ok;
1700                 }
1701
1702                 public void EmitAttributes ()
1703                 {
1704                         for (int i = 0; i < TypeParameters.Length; i++)
1705                                 TypeParameters [i].Emit ();
1706
1707                         if (OptAttributes != null)
1708                                 OptAttributes.Emit ();
1709                 }
1710
1711                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1712                                                         MemberFilter filter, object criteria)
1713                 {
1714                         throw new Exception ();
1715                 }               
1716
1717                 public override MemberCache MemberCache {
1718                         get {
1719                                 return null;
1720                         }
1721                 }
1722
1723                 public override AttributeTargets AttributeTargets {
1724                         get {
1725                                 return AttributeTargets.Method | AttributeTargets.ReturnValue;
1726                         }
1727                 }
1728
1729                 public override string DocCommentHeader {
1730                         get { return "M:"; }
1731                 }
1732
1733                 public new void VerifyClsCompliance ()
1734                 {
1735                         foreach (TypeParameter tp in TypeParameters) {
1736                                 if (tp.Constraints == null)
1737                                         continue;
1738
1739                                 tp.Constraints.VerifyClsCompliance ();
1740                         }
1741                 }
1742         }
1743
1744         public partial class TypeManager
1745         {
1746                 static public Type activator_type;
1747         
1748                 public static TypeContainer LookupGenericTypeContainer (Type t)
1749                 {
1750                         t = DropGenericTypeArguments (t);
1751                         return LookupTypeContainer (t);
1752                 }
1753
1754                 /// <summary>
1755                 ///   Check whether `a' and `b' may become equal generic types.
1756                 ///   The algorithm to do that is a little bit complicated.
1757                 /// </summary>
1758                 public static bool MayBecomeEqualGenericTypes (Type a, Type b, Type[] class_inferred,
1759                                                                Type[] method_inferred)
1760                 {
1761                         if (a.IsGenericParameter) {
1762                                 //
1763                                 // If a is an array of a's type, they may never
1764                                 // become equal.
1765                                 //
1766                                 while (b.IsArray) {
1767                                         b = GetElementType (b);
1768                                         if (a.Equals (b))
1769                                                 return false;
1770                                 }
1771
1772                                 //
1773                                 // If b is a generic parameter or an actual type,
1774                                 // they may become equal:
1775                                 //
1776                                 //    class X<T,U> : I<T>, I<U>
1777                                 //    class X<T> : I<T>, I<float>
1778                                 // 
1779                                 if (b.IsGenericParameter || !b.IsGenericType) {
1780                                         int pos = a.GenericParameterPosition;
1781                                         Type[] args = a.DeclaringMethod != null ? method_inferred : class_inferred;
1782                                         if (args [pos] == null) {
1783                                                 args [pos] = b;
1784                                                 return true;
1785                                         }
1786
1787                                         return args [pos] == a;
1788                                 }
1789
1790                                 //
1791                                 // We're now comparing a type parameter with a
1792                                 // generic instance.  They may become equal unless
1793                                 // the type parameter appears anywhere in the
1794                                 // generic instance:
1795                                 //
1796                                 //    class X<T,U> : I<T>, I<X<U>>
1797                                 //        -> error because you could instanciate it as
1798                                 //           X<X<int>,int>
1799                                 //
1800                                 //    class X<T> : I<T>, I<X<T>> -> ok
1801                                 //
1802
1803                                 Type[] bargs = GetTypeArguments (b);
1804                                 for (int i = 0; i < bargs.Length; i++) {
1805                                         if (a.Equals (bargs [i]))
1806                                                 return false;
1807                                 }
1808
1809                                 return true;
1810                         }
1811
1812                         if (b.IsGenericParameter)
1813                                 return MayBecomeEqualGenericTypes (b, a, class_inferred, method_inferred);
1814
1815                         //
1816                         // At this point, neither a nor b are a type parameter.
1817                         //
1818                         // If one of them is a generic instance, let
1819                         // MayBecomeEqualGenericInstances() compare them (if the
1820                         // other one is not a generic instance, they can never
1821                         // become equal).
1822                         //
1823
1824                         if (a.IsGenericType || b.IsGenericType)
1825                                 return MayBecomeEqualGenericInstances (a, b, class_inferred, method_inferred);
1826
1827                         //
1828                         // If both of them are arrays.
1829                         //
1830
1831                         if (a.IsArray && b.IsArray) {
1832                                 if (a.GetArrayRank () != b.GetArrayRank ())
1833                                         return false;
1834                         
1835                                 a = GetElementType (a);
1836                                 b = GetElementType (b);
1837
1838                                 return MayBecomeEqualGenericTypes (a, b, class_inferred, method_inferred);
1839                         }
1840
1841                         //
1842                         // Ok, two ordinary types.
1843                         //
1844
1845                         return a.Equals (b);
1846                 }
1847
1848                 //
1849                 // Checks whether two generic instances may become equal for some
1850                 // particular instantiation (26.3.1).
1851                 //
1852                 public static bool MayBecomeEqualGenericInstances (Type a, Type b,
1853                                                                    Type[] class_inferred,
1854                                                                    Type[] method_inferred)
1855                 {
1856                         if (!a.IsGenericType || !b.IsGenericType)
1857                                 return false;
1858                         if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
1859                                 return false;
1860
1861                         return MayBecomeEqualGenericInstances (
1862                                 GetTypeArguments (a), GetTypeArguments (b), class_inferred, method_inferred);
1863                 }
1864
1865                 public static bool MayBecomeEqualGenericInstances (Type[] aargs, Type[] bargs,
1866                                                                    Type[] class_inferred,
1867                                                                    Type[] method_inferred)
1868                 {
1869                         if (aargs.Length != bargs.Length)
1870                                 return false;
1871
1872                         for (int i = 0; i < aargs.Length; i++) {
1873                                 if (!MayBecomeEqualGenericTypes (aargs [i], bargs [i], class_inferred, method_inferred))
1874                                         return false;
1875                         }
1876
1877                         return true;
1878                 }
1879
1880                 /// <summary>
1881                 ///   Type inference.  Try to infer the type arguments from `method',
1882                 ///   which is invoked with the arguments `arguments'.  This is used
1883                 ///   when resolving an Invocation or a DelegateInvocation and the user
1884                 ///   did not explicitly specify type arguments.
1885                 /// </summary>
1886                 public static int InferTypeArguments (EmitContext ec,
1887                                                        ArrayList arguments,
1888                                                        ref MethodBase method)
1889                 {
1890                         ATypeInference ti = ATypeInference.CreateInstance (arguments);
1891                         Type[] i_args = ti.InferMethodArguments (ec, method);
1892                         if (i_args == null)
1893                                 return ti.InferenceScore;
1894
1895                         if (i_args.Length == 0)
1896                                 return 0;
1897
1898                         method = ((MethodInfo) method).MakeGenericMethod (i_args);
1899                         return 0;
1900                 }
1901
1902                 /// <summary>
1903                 ///   Type inference.
1904                 /// </summary>
1905                 public static bool InferTypeArguments (AParametersCollection apd,
1906                                                        ref MethodBase method)
1907                 {
1908                         if (!TypeManager.IsGenericMethod (method))
1909                                 return true;
1910
1911                         ATypeInference ti = ATypeInference.CreateInstance (ArrayList.Adapter (apd.Types));
1912                         Type[] i_args = ti.InferDelegateArguments (method);
1913                         if (i_args == null)
1914                                 return false;
1915
1916                         method = ((MethodInfo) method).MakeGenericMethod (i_args);
1917                         return true;
1918                 }
1919         }
1920
1921         abstract class ATypeInference
1922         {
1923                 protected readonly ArrayList arguments;
1924                 protected readonly int arg_count;
1925
1926                 protected ATypeInference (ArrayList arguments)
1927                 {
1928                         this.arguments = arguments;
1929                         if (arguments != null)
1930                                 arg_count = arguments.Count;
1931                 }
1932
1933                 public static ATypeInference CreateInstance (ArrayList arguments)
1934                 {
1935                         if (RootContext.Version == LanguageVersion.ISO_2)
1936                                 return new TypeInferenceV2 (arguments);
1937
1938                         return new TypeInferenceV3 (arguments);
1939                 }
1940
1941                 public virtual int InferenceScore {
1942                         get {
1943                                 return int.MaxValue;
1944                         }
1945                 }
1946
1947                 public abstract Type[] InferMethodArguments (EmitContext ec, MethodBase method);
1948                 public abstract Type[] InferDelegateArguments (MethodBase method);
1949         }
1950
1951         //
1952         // Implements C# 2.0 type inference
1953         //
1954         class TypeInferenceV2 : ATypeInference
1955         {
1956                 public TypeInferenceV2 (ArrayList arguments)
1957                         : base (arguments)
1958                 {
1959                 }
1960
1961                 public override Type[] InferDelegateArguments (MethodBase method)
1962                 {
1963                         AParametersCollection pd = TypeManager.GetParameterData (method);
1964                         if (arg_count != pd.Count)
1965                                 return null;
1966
1967                         Type[] method_args = method.GetGenericArguments ();
1968                         Type[] inferred_types = new Type[method_args.Length];
1969
1970                         Type[] param_types = new Type[pd.Count];
1971                         Type[] arg_types = (Type[])arguments.ToArray (typeof (Type));
1972
1973                         for (int i = 0; i < arg_count; i++) {
1974                                 param_types[i] = pd.Types [i];
1975                         }
1976
1977                         if (!InferTypeArguments (param_types, arg_types, inferred_types))
1978                                 return null;
1979
1980                         return inferred_types;
1981                 }
1982
1983                 public override Type[] InferMethodArguments (EmitContext ec, MethodBase method)
1984                 {
1985                         AParametersCollection pd = TypeManager.GetParameterData (method);
1986                         Type[] method_generic_args = method.GetGenericArguments ();
1987                         Type [] inferred_types = new Type [method_generic_args.Length];
1988                         Type[] arg_types = new Type [pd.Count];
1989
1990                         int a_count = arg_types.Length;
1991                         if (pd.HasParams)
1992                                 --a_count;
1993
1994                         for (int i = 0; i < a_count; i++) {
1995                                 Argument a = (Argument) arguments[i];
1996                                 if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
1997                                         continue;
1998
1999                                 if (!TypeInferenceV2.UnifyType (pd.Types [i], a.Type, inferred_types))
2000                                         return null;
2001                         }
2002
2003                         if (pd.HasParams) {
2004                                 Type element_type = TypeManager.GetElementType (pd.Types [a_count]);
2005                                 for (int i = a_count; i < arg_count; i++) {
2006                                         Argument a = (Argument) arguments [i];
2007                                         if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
2008                                                 continue;
2009
2010                                         if (!TypeInferenceV2.UnifyType (element_type, a.Type, inferred_types))
2011                                                 return null;
2012                                 }
2013                         }
2014
2015                         for (int i = 0; i < inferred_types.Length; i++)
2016                                 if (inferred_types [i] == null)
2017                                         return null;
2018
2019                         return inferred_types;
2020                 }
2021
2022                 static bool InferTypeArguments (Type[] param_types, Type[] arg_types,
2023                                 Type[] inferred_types)
2024                 {
2025                         for (int i = 0; i < arg_types.Length; i++) {
2026                                 if (arg_types[i] == null)
2027                                         continue;
2028
2029                                 if (!UnifyType (param_types[i], arg_types[i], inferred_types))
2030                                         return false;
2031                         }
2032
2033                         for (int i = 0; i < inferred_types.Length; ++i)
2034                                 if (inferred_types[i] == null)
2035                                         return false;
2036
2037                         return true;
2038                 }
2039
2040                 public static bool UnifyType (Type pt, Type at, Type[] inferred)
2041                 {
2042                         if (pt.IsGenericParameter) {
2043                                 if (pt.DeclaringMethod == null)
2044                                         return pt == at;
2045
2046                                 int pos = pt.GenericParameterPosition;
2047
2048                                 if (inferred [pos] == null)
2049                                         inferred [pos] = at;
2050
2051                                 return inferred [pos] == at;
2052                         }
2053
2054                         if (!pt.ContainsGenericParameters) {
2055                                 if (at.ContainsGenericParameters)
2056                                         return UnifyType (at, pt, inferred);
2057                                 else
2058                                         return true;
2059                         }
2060
2061                         if (at.IsArray) {
2062                                 if (pt.IsArray) {
2063                                         if (at.GetArrayRank () != pt.GetArrayRank ())
2064                                                 return false;
2065
2066                                         return UnifyType (TypeManager.GetElementType (pt), TypeManager.GetElementType (at), inferred);
2067                                 }
2068
2069                                 if (!pt.IsGenericType)
2070                                         return false;
2071
2072                                 Type gt = pt.GetGenericTypeDefinition ();
2073                                 if ((gt != TypeManager.generic_ilist_type) && (gt != TypeManager.generic_icollection_type) &&
2074                                         (gt != TypeManager.generic_ienumerable_type))
2075                                         return false;
2076
2077                                 Type[] args = TypeManager.GetTypeArguments (pt);
2078                                 return UnifyType (args[0], at.GetElementType (), inferred);
2079                         }
2080
2081                         if (pt.IsArray) {
2082                                 if (!at.IsArray ||
2083                                         (pt.GetArrayRank () != at.GetArrayRank ()))
2084                                         return false;
2085
2086                                 return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
2087                         }
2088
2089                         if (pt.IsByRef && at.IsByRef)
2090                                 return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
2091                         ArrayList list = new ArrayList ();
2092                         if (at.IsGenericType)
2093                                 list.Add (at);
2094                         for (Type bt = at.BaseType; bt != null; bt = bt.BaseType)
2095                                 list.Add (bt);
2096
2097                         list.AddRange (TypeManager.GetInterfaces (at));
2098
2099                         foreach (Type type in list) {
2100                                 if (!type.IsGenericType)
2101                                         continue;
2102
2103                                 if (TypeManager.DropGenericTypeArguments (pt) != TypeManager.DropGenericTypeArguments (type))
2104                                         continue;
2105
2106                                 if (!UnifyTypes (pt.GetGenericArguments (), type.GetGenericArguments (), inferred))
2107                                         return false;
2108                         }
2109
2110                         return true;
2111                 }
2112
2113                 static bool UnifyTypes (Type[] pts, Type[] ats, Type[] inferred)
2114                 {
2115                         for (int i = 0; i < ats.Length; i++) {
2116                                 if (!UnifyType (pts [i], ats [i], inferred))
2117                                         return false;
2118                         }
2119                         return true;
2120                 }
2121         }
2122
2123         //
2124         // Implements C# 3.0 type inference
2125         //
2126         class TypeInferenceV3 : ATypeInference
2127         {
2128                 //
2129                 // Tracks successful rate of type inference
2130                 //
2131                 int score = int.MaxValue;
2132
2133                 public TypeInferenceV3 (ArrayList arguments)
2134                         : base (arguments)
2135                 {
2136                 }
2137
2138                 public override int InferenceScore {
2139                         get {
2140                                 return score;
2141                         }
2142                 }
2143
2144                 public override Type[] InferDelegateArguments (MethodBase method)
2145                 {
2146                         AParametersCollection pd = TypeManager.GetParameterData (method);
2147                         if (arg_count != pd.Count)
2148                                 return null;
2149
2150                         Type[] d_gargs = method.GetGenericArguments ();
2151                         TypeInferenceContext context = new TypeInferenceContext (d_gargs);
2152
2153                         // A lower-bound inference is made from each argument type Uj of D
2154                         // to the corresponding parameter type Tj of M
2155                         for (int i = 0; i < arg_count; ++i) {
2156                                 Type t = pd.Types [i];
2157                                 if (!t.IsGenericParameter)
2158                                         continue;
2159
2160                                 context.LowerBoundInference ((Type)arguments[i], t);
2161                         }
2162
2163                         if (!context.FixAllTypes ())
2164                                 return null;
2165
2166                         return context.InferredTypeArguments;
2167                 }
2168
2169                 public override Type[] InferMethodArguments (EmitContext ec, MethodBase method)
2170                 {
2171                         Type[] method_generic_args = method.GetGenericArguments ();
2172                         TypeInferenceContext context = new TypeInferenceContext (method_generic_args);
2173                         if (!context.UnfixedVariableExists)
2174                                 return Type.EmptyTypes;
2175
2176                         AParametersCollection pd = TypeManager.GetParameterData (method);
2177                         if (!InferInPhases (ec, context, pd))
2178                                 return null;
2179
2180                         return context.InferredTypeArguments;
2181                 }
2182
2183                 //
2184                 // Implements method type arguments inference
2185                 //
2186                 bool InferInPhases (EmitContext ec, TypeInferenceContext tic, AParametersCollection methodParameters)
2187                 {
2188                         int params_arguments_start;
2189                         if (methodParameters.HasParams) {
2190                                 params_arguments_start = methodParameters.Count - 1;
2191                         } else {
2192                                 params_arguments_start = arg_count;
2193                         }
2194
2195                         Type [] ptypes = methodParameters.Types;
2196                         
2197                         //
2198                         // The first inference phase
2199                         //
2200                         Type method_parameter = null;
2201                         for (int i = 0; i < arg_count; i++) {
2202                                 Argument a = (Argument) arguments [i];
2203                                 
2204                                 if (i < params_arguments_start) {
2205                                         method_parameter = methodParameters.Types [i];
2206                                 } else if (i == params_arguments_start) {
2207                                         if (arg_count == params_arguments_start + 1 && TypeManager.HasElementType (a.Type))
2208                                                 method_parameter = methodParameters.Types [params_arguments_start];
2209                                         else
2210                                                 method_parameter = TypeManager.GetElementType (methodParameters.Types [params_arguments_start]);
2211
2212                                         ptypes = (Type[]) ptypes.Clone ();
2213                                         ptypes [i] = method_parameter;
2214                                 }
2215
2216                                 //
2217                                 // When a lambda expression, an anonymous method
2218                                 // is used an explicit argument type inference takes a place
2219                                 //
2220                                 AnonymousMethodExpression am = a.Expr as AnonymousMethodExpression;
2221                                 if (am != null) {
2222                                         if (am.ExplicitTypeInference (tic, method_parameter))
2223                                                 --score; 
2224                                         continue;
2225                                 }
2226
2227                                 if (a.Expr is NullLiteral)
2228                                         continue;
2229
2230                                 //
2231                                 // Otherwise an output type inference is made
2232                                 //
2233                                 score -= tic.OutputTypeInference (ec, a.Expr, method_parameter);
2234                         }
2235
2236                         //
2237                         // Part of the second phase but because it happens only once
2238                         // we don't need to call it in cycle
2239                         //
2240                         bool fixed_any = false;
2241                         if (!tic.FixIndependentTypeArguments (ptypes, ref fixed_any))
2242                                 return false;
2243
2244                         return DoSecondPhase (ec, tic, ptypes, !fixed_any);
2245                 }
2246
2247                 bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, Type[] methodParameters, bool fixDependent)
2248                 {
2249                         bool fixed_any = false;
2250                         if (fixDependent && !tic.FixDependentTypes (ref fixed_any))
2251                                 return false;
2252
2253                         // If no further unfixed type variables exist, type inference succeeds
2254                         if (!tic.UnfixedVariableExists)
2255                                 return true;
2256
2257                         if (!fixed_any && fixDependent)
2258                                 return false;
2259                         
2260                         // For all arguments where the corresponding argument output types
2261                         // contain unfixed type variables but the input types do not,
2262                         // an output type inference is made
2263                         for (int i = 0; i < arg_count; i++) {
2264                                 
2265                                 // Align params arguments
2266                                 Type t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i];
2267                                 
2268                                 if (!TypeManager.IsDelegateType (t_i)) {
2269                                         if (TypeManager.DropGenericTypeArguments (t_i) != TypeManager.expression_type)
2270                                                 continue;
2271
2272                                         t_i = t_i.GetGenericArguments () [0];
2273                                 }
2274
2275                                 MethodInfo mi = Delegate.GetInvokeMethod (t_i, t_i);
2276                                 Type rtype = mi.ReturnType;
2277
2278 #if MS_COMPATIBLE
2279                                 // Blablabla, because reflection does not work with dynamic types
2280                                 Type[] g_args = t_i.GetGenericArguments ();
2281                                 rtype = g_args[rtype.GenericParameterPosition];
2282 #endif
2283
2284                                 if (tic.IsReturnTypeNonDependent (mi, rtype))
2285                                         score -= tic.OutputTypeInference (ec, ((Argument) arguments [i]).Expr, t_i);
2286                         }
2287
2288
2289                         return DoSecondPhase (ec, tic, methodParameters, true);
2290                 }
2291         }
2292
2293         public class TypeInferenceContext
2294         {
2295                 readonly Type[] unfixed_types;
2296                 readonly Type[] fixed_types;
2297                 readonly ArrayList[] bounds;
2298                 bool failed;
2299                 
2300                 public TypeInferenceContext (Type[] typeArguments)
2301                 {
2302                         if (typeArguments.Length == 0)
2303                                 throw new ArgumentException ("Empty generic arguments");
2304
2305                         fixed_types = new Type [typeArguments.Length];
2306                         for (int i = 0; i < typeArguments.Length; ++i) {
2307                                 if (typeArguments [i].IsGenericParameter) {
2308                                         if (bounds == null) {
2309                                                 bounds = new ArrayList [typeArguments.Length];
2310                                                 unfixed_types = new Type [typeArguments.Length];
2311                                         }
2312                                         unfixed_types [i] = typeArguments [i];
2313                                 } else {
2314                                         fixed_types [i] = typeArguments [i];
2315                                 }
2316                         }
2317                 }
2318
2319                 public Type[] InferredTypeArguments {
2320                         get {
2321                                 return fixed_types;
2322                         }
2323                 }
2324
2325                 void AddToBounds (Type t, int index)
2326                 {
2327                         //
2328                         // Some types cannot be used as type arguments
2329                         //
2330                         if (t == TypeManager.void_type || t.IsPointer)
2331                                 return;
2332
2333                         ArrayList a = bounds [index];
2334                         if (a == null) {
2335                                 a = new ArrayList ();
2336                                 bounds [index] = a;
2337                         } else {
2338                                 if (a.Contains (t))
2339                                         return;
2340                         }
2341
2342                         //
2343                         // SPEC: does not cover type inference using constraints
2344                         //
2345                         //if (TypeManager.IsGenericParameter (t)) {
2346                         //    GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
2347                         //    if (constraints != null) {
2348                         //        //if (constraints.EffectiveBaseClass != null)
2349                         //        //    t = constraints.EffectiveBaseClass;
2350                         //    }
2351                         //}
2352                         a.Add (t);
2353                 }
2354                 
2355                 bool AllTypesAreFixed (Type[] types)
2356                 {
2357                         foreach (Type t in types) {
2358                                 if (t.IsGenericParameter) {
2359                                         if (!IsFixed (t))
2360                                                 return false;
2361                                         continue;
2362                                 }
2363
2364                                 if (t.IsGenericType)
2365                                         return AllTypesAreFixed (t.GetGenericArguments ());
2366                         }
2367                         
2368                         return true;
2369                 }               
2370
2371                 //
2372                 // 26.3.3.8 Exact Inference
2373                 //
2374                 public int ExactInference (Type u, Type v)
2375                 {
2376                         // If V is an array type
2377                         if (v.IsArray) {
2378                                 if (!u.IsArray)
2379                                         return 0;
2380
2381                                 if (u.GetArrayRank () != v.GetArrayRank ())
2382                                         return 0;
2383
2384                                 return ExactInference (TypeManager.GetElementType (u), TypeManager.GetElementType (v));
2385                         }
2386
2387                         // If V is constructed type and U is constructed type
2388                         if (v.IsGenericType && !v.IsGenericTypeDefinition) {
2389                                 if (!u.IsGenericType)
2390                                         return 0;
2391
2392                                 Type [] ga_u = u.GetGenericArguments ();
2393                                 Type [] ga_v = v.GetGenericArguments ();
2394                                 if (ga_u.Length != ga_v.Length)
2395                                         return 0;
2396
2397                                 int score = 0;
2398                                 for (int i = 0; i < ga_u.Length; ++i)
2399                                         score += ExactInference (ga_u [i], ga_v [i]);
2400
2401                                 return score > 0 ? 1 : 0;
2402                         }
2403
2404                         // If V is one of the unfixed type arguments
2405                         int pos = IsUnfixed (v);
2406                         if (pos == -1)
2407                                 return 0;
2408
2409                         AddToBounds (u, pos);
2410                         return 1;
2411                 }
2412
2413                 public bool FixAllTypes ()
2414                 {
2415                         for (int i = 0; i < unfixed_types.Length; ++i) {
2416                                 if (!FixType (i))
2417                                         return false;
2418                         }
2419                         return true;
2420                 }
2421
2422                 //
2423                 // All unfixed type variables Xi are fixed for which all of the following hold:
2424                 // a, There is at least one type variable Xj that depends on Xi
2425                 // b, Xi has a non-empty set of bounds
2426                 // 
2427                 public bool FixDependentTypes (ref bool fixed_any)
2428                 {
2429                         for (int i = 0; i < unfixed_types.Length; ++i) {
2430                                 if (unfixed_types[i] == null)
2431                                         continue;
2432
2433                                 if (bounds[i] == null)
2434                                         continue;
2435
2436                                 if (!FixType (i))
2437                                         return false;
2438                                 
2439                                 fixed_any = true;
2440                         }
2441
2442                         return true;
2443                 }
2444
2445                 //
2446                 // All unfixed type variables Xi which depend on no Xj are fixed
2447                 //
2448                 public bool FixIndependentTypeArguments (Type[] methodParameters, ref bool fixed_any)
2449                 {
2450                         ArrayList types_to_fix = new ArrayList (unfixed_types);
2451                         for (int i = 0; i < methodParameters.Length; ++i) {
2452                                 Type t = methodParameters[i];
2453                                 if (t.IsGenericParameter)
2454                                         continue;
2455
2456                                 if (!TypeManager.IsDelegateType (t)) {
2457                                         if (TypeManager.DropGenericTypeArguments (t) != TypeManager.expression_type)
2458                                                 continue;
2459
2460                                         t = t.GetGenericArguments () [0];
2461                                 }
2462
2463                                 MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
2464                                 Type rtype = invoke.ReturnType;
2465                                 if (!rtype.IsGenericParameter && !rtype.IsGenericType)
2466                                         continue;
2467
2468 #if MS_COMPATIBLE
2469                                 // Blablabla, because reflection does not work with dynamic types
2470                                 if (rtype.IsGenericParameter) {
2471                                         Type [] g_args = t.GetGenericArguments ();
2472                                         rtype = g_args [rtype.GenericParameterPosition];
2473                                 }
2474 #endif
2475                                 // Remove dependent types, they cannot be fixed yet
2476                                 RemoveDependentTypes (types_to_fix, rtype);
2477                         }
2478
2479                         foreach (Type t in types_to_fix) {
2480                                 if (t == null)
2481                                         continue;
2482
2483                                 int idx = IsUnfixed (t);
2484                                 if (idx >= 0 && !FixType (idx)) {
2485                                         return false;
2486                                 }
2487                         }
2488
2489                         fixed_any = types_to_fix.Count > 0;
2490                         return true;
2491                 }
2492
2493                 //
2494                 // 26.3.3.10 Fixing
2495                 //
2496                 public bool FixType (int i)
2497                 {
2498                         // It's already fixed
2499                         if (unfixed_types[i] == null)
2500                                 throw new InternalErrorException ("Type argument has been already fixed");
2501
2502                         if (failed)
2503                                 return false;
2504
2505                         ArrayList candidates = (ArrayList)bounds [i];
2506                         if (candidates == null)
2507                                 return false;
2508
2509                         if (candidates.Count == 1) {
2510                                 unfixed_types[i] = null;
2511                                 fixed_types[i] = (Type)candidates[0];
2512                                 return true;
2513                         }
2514
2515                         //
2516                         // Determines a unique type from which there is
2517                         // a standard implicit conversion to all the other
2518                         // candidate types.
2519                         //
2520                         Type best_candidate = null;
2521                         int cii;
2522                         int candidates_count = candidates.Count;
2523                         for (int ci = 0; ci < candidates_count; ++ci) {
2524                                 Type candidate = (Type)candidates [ci];
2525                                 for (cii = 0; cii < candidates_count; ++cii) {
2526                                         if (cii == ci)
2527                                                 continue;
2528
2529                                         if (!Convert.ImplicitConversionExists (null,
2530                                                 new TypeExpression ((Type)candidates [cii], Location.Null), candidate)) {
2531                                                 break;
2532                                         }
2533                                 }
2534
2535                                 if (cii != candidates_count)
2536                                         continue;
2537
2538                                 if (best_candidate != null)
2539                                         return false;
2540
2541                                 best_candidate = candidate;
2542                         }
2543
2544                         if (best_candidate == null)
2545                                 return false;
2546
2547                         unfixed_types[i] = null;
2548                         fixed_types[i] = best_candidate;
2549                         return true;
2550                 }
2551                 
2552                 //
2553                 // Uses inferred types to inflate delegate type argument
2554                 //
2555                 public Type InflateGenericArgument (Type parameter)
2556                 {
2557                         if (parameter.IsGenericParameter) {
2558                                 //
2559                                 // Inflate method generic argument (MVAR) only
2560                                 //
2561                                 if (parameter.DeclaringMethod == null)
2562                                         return parameter;
2563
2564                                 return fixed_types [parameter.GenericParameterPosition];
2565                         }
2566
2567                         if (parameter.IsGenericType) {
2568                                 Type [] parameter_targs = parameter.GetGenericArguments ();
2569                                 for (int ii = 0; ii < parameter_targs.Length; ++ii) {
2570                                         parameter_targs [ii] = InflateGenericArgument (parameter_targs [ii]);
2571                                 }
2572                                 return parameter.GetGenericTypeDefinition ().MakeGenericType (parameter_targs);
2573                         }
2574
2575                         return parameter;
2576                 }
2577                 
2578                 //
2579                 // Tests whether all delegate input arguments are fixed and generic output type
2580                 // requires output type inference 
2581                 //
2582                 public bool IsReturnTypeNonDependent (MethodInfo invoke, Type returnType)
2583                 {
2584                         if (returnType.IsGenericParameter) {
2585                                 if (IsFixed (returnType))
2586                                     return false;
2587                         } else if (returnType.IsGenericType) {
2588                                 if (TypeManager.IsDelegateType (returnType)) {
2589                                         invoke = Delegate.GetInvokeMethod (returnType, returnType);
2590                                         return IsReturnTypeNonDependent (invoke, invoke.ReturnType);
2591                                 }
2592                                         
2593                                 Type[] g_args = returnType.GetGenericArguments ();
2594                                 
2595                                 // At least one unfixed return type has to exist 
2596                                 if (AllTypesAreFixed (g_args))
2597                                         return false;
2598                         } else {
2599                                 return false;
2600                         }
2601
2602                         // All generic input arguments have to be fixed
2603                         AParametersCollection d_parameters = TypeManager.GetParameterData (invoke);
2604                         return AllTypesAreFixed (d_parameters.Types);
2605                 }
2606                 
2607                 bool IsFixed (Type type)
2608                 {
2609                         return IsUnfixed (type) == -1;
2610                 }               
2611
2612                 int IsUnfixed (Type type)
2613                 {
2614                         if (!type.IsGenericParameter)
2615                                 return -1;
2616
2617                         //return unfixed_types[type.GenericParameterPosition] != null;
2618                         for (int i = 0; i < unfixed_types.Length; ++i) {
2619                                 if (unfixed_types [i] == type)
2620                                         return i;
2621                         }
2622
2623                         return -1;
2624                 }
2625
2626                 //
2627                 // 26.3.3.9 Lower-bound Inference
2628                 //
2629                 public int LowerBoundInference (Type u, Type v)
2630                 {
2631                         // If V is one of the unfixed type arguments
2632                         int pos = IsUnfixed (v);
2633                         if (pos != -1) {
2634                                 AddToBounds (u, pos);
2635                                 return 1;
2636                         }                       
2637
2638                         // If U is an array type
2639                         if (u.IsArray) {
2640                                 int u_dim = u.GetArrayRank ();
2641                                 Type v_e;
2642                                 Type u_e = TypeManager.GetElementType (u);
2643
2644                                 if (v.IsArray) {
2645                                         if (u_dim != v.GetArrayRank ())
2646                                                 return 0;
2647
2648                                         v_e = TypeManager.GetElementType (v);
2649
2650                                         if (u.IsByRef) {
2651                                                 return LowerBoundInference (u_e, v_e);
2652                                         }
2653
2654                                         return ExactInference (u_e, v_e);
2655                                 }
2656
2657                                 if (u_dim != 1)
2658                                         return 0;
2659
2660                                 if (v.IsGenericType) {
2661                                         Type g_v = v.GetGenericTypeDefinition ();
2662                                         if ((g_v != TypeManager.generic_ilist_type) && (g_v != TypeManager.generic_icollection_type) &&
2663                                                 (g_v != TypeManager.generic_ienumerable_type))
2664                                                 return 0;
2665
2666                                         v_e = TypeManager.GetTypeArguments (v)[0];
2667
2668                                         if (u.IsByRef) {
2669                                                 return LowerBoundInference (u_e, v_e);
2670                                         }
2671
2672                                         return ExactInference (u_e, v_e);
2673                                 }
2674                         } else if (v.IsGenericType && !v.IsGenericTypeDefinition) {
2675                                 //
2676                                 // if V is a constructed type C<V1..Vk> and there is a unique set of types U1..Uk
2677                                 // such that a standard implicit conversion exists from U to C<U1..Uk> then an exact
2678                                 // inference is made from each Ui for the corresponding Vi
2679                                 //
2680                                 ArrayList u_candidates = new ArrayList ();
2681                                 if (u.IsGenericType)
2682                                         u_candidates.Add (u);
2683
2684                                 for (Type t = u.BaseType; t != null; t = t.BaseType) {
2685                                         if (t.IsGenericType && !t.IsGenericTypeDefinition)
2686                                                 u_candidates.Add (t);
2687                                 }
2688
2689                                 // TODO: Implement GetGenericInterfaces only and remove
2690                                 // the if from foreach
2691                                 u_candidates.AddRange (TypeManager.GetInterfaces (u));
2692
2693                                 Type open_v = v.GetGenericTypeDefinition ();
2694                                 Type [] unique_candidate_targs = null;
2695                                 Type [] ga_v = v.GetGenericArguments ();                        
2696                                 foreach (Type u_candidate in u_candidates) {
2697                                         if (!u_candidate.IsGenericType || u_candidate.IsGenericTypeDefinition)
2698                                                 continue;
2699
2700                                         if (TypeManager.DropGenericTypeArguments (u_candidate) != open_v)
2701                                                 continue;
2702
2703                                         //
2704                                         // The unique set of types U1..Uk means that if we have an interface C<T>,
2705                                         // class U: C<int>, C<long> then no type inference is made when inferring
2706                                         // from U to C<T> because T could be int or long
2707                                         //
2708                                         if (unique_candidate_targs != null) {
2709                                                 Type[] second_unique_candidate_targs = u_candidate.GetGenericArguments ();
2710                                                 if (TypeManager.IsEqual (unique_candidate_targs, second_unique_candidate_targs)) {
2711                                                         unique_candidate_targs = second_unique_candidate_targs;
2712                                                         continue;
2713                                                 }
2714                                                 
2715                                                 //
2716                                                 // This should always cause type inference failure
2717                                                 //
2718                                                 failed = true;
2719                                                 return 1;
2720                                         }
2721
2722                                         unique_candidate_targs = u_candidate.GetGenericArguments ();
2723                                 }
2724
2725                                 if (unique_candidate_targs != null) {
2726                                         int score = 0;
2727                                         for (int i = 0; i < unique_candidate_targs.Length; ++i)
2728                                                 if (ExactInference (unique_candidate_targs [i], ga_v [i]) == 0)
2729                                                         ++score;
2730                                         return score;
2731                                 }
2732                         }
2733
2734                         return 0;
2735                 }
2736
2737                 //
2738                 // 26.3.3.6 Output Type Inference
2739                 //
2740                 public int OutputTypeInference (EmitContext ec, Expression e, Type t)
2741                 {
2742                         // If e is a lambda or anonymous method with inferred return type
2743                         AnonymousMethodExpression ame = e as AnonymousMethodExpression;
2744                         if (ame != null) {
2745                                 Type rt = ame.InferReturnType (ec, this, t);
2746                                 MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
2747
2748                                 if (rt == null) {
2749                                         AParametersCollection pd = TypeManager.GetParameterData (invoke);
2750                                         return ame.Parameters.Count == pd.Count ? 1 : 0;
2751                                 }
2752
2753                                 Type rtype = invoke.ReturnType;
2754 #if MS_COMPATIBLE
2755                                 // Blablabla, because reflection does not work with dynamic types
2756                                 Type [] g_args = t.GetGenericArguments ();
2757                                 rtype = g_args [rtype.GenericParameterPosition];
2758 #endif
2759                                 return LowerBoundInference (rt, rtype) + 1;
2760                         }
2761
2762                         //
2763                         // if E is a method group and T is a delegate type or expression tree type
2764                         // return type Tb with parameter types T1..Tk and return type Tb, and overload
2765                         // resolution of E with the types T1..Tk yields a single method with return type U,
2766                         // then a lower-bound inference is made from U for Tb.
2767                         //
2768                         if (e is MethodGroupExpr) {
2769                                 // TODO: Or expression tree
2770                                 if (!TypeManager.IsDelegateType (t))
2771                                         return 0;
2772
2773                                 MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
2774                                 Type rtype = invoke.ReturnType;
2775 #if MS_COMPATIBLE
2776                                 // Blablabla, because reflection does not work with dynamic types
2777                                 Type [] g_args = t.GetGenericArguments ();
2778                                 rtype = g_args [rtype.GenericParameterPosition];
2779 #endif
2780
2781                                 if (!TypeManager.IsGenericType (rtype))
2782                                         return 0;
2783
2784                                 MethodGroupExpr mg = (MethodGroupExpr) e;
2785                                 ArrayList args = DelegateCreation.CreateDelegateMethodArguments (invoke, e.Location);
2786                                 mg = mg.OverloadResolve (ec, ref args, true, e.Location);
2787                                 if (mg == null)
2788                                         return 0;
2789
2790                                 // TODO: What should happen when return type is of generic type ?
2791                                 throw new NotImplementedException ();
2792 //                              return LowerBoundInference (null, rtype) + 1;
2793                         }
2794
2795                         //
2796                         // if e is an expression with type U, then
2797                         // a lower-bound inference is made from U for T
2798                         //
2799                         return LowerBoundInference (e.Type, t) * 2;
2800                 }
2801
2802                 void RemoveDependentTypes (ArrayList types, Type returnType)
2803                 {
2804                         int idx = IsUnfixed (returnType);
2805                         if (idx >= 0) {
2806                                 types [idx] = null;
2807                                 return;
2808                         }
2809
2810                         if (returnType.IsGenericType) {
2811                                 foreach (Type t in returnType.GetGenericArguments ()) {
2812                                         RemoveDependentTypes (types, t);
2813                                 }
2814                         }
2815                 }
2816
2817                 public bool UnfixedVariableExists {
2818                         get {
2819                                 if (unfixed_types == null)
2820                                         return false;
2821
2822                                 foreach (Type ut in unfixed_types)
2823                                         if (ut != null)
2824                                                 return true;
2825                                 return false;
2826                         }
2827                 }
2828         }
2829 }