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