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