Update lower/upper type inference fixing to match the latest C# standard. Fixes ...
[mono.git] / mcs / mcs / generic.cs
index aeb3e849b744a1a9777dc75f8c60c7c9ff99f2b4..5a24c6898b5f8d0744eef1d11519e4320171d818 100644 (file)
@@ -28,6 +28,50 @@ using System.Reflection.Emit;
 #endif
 
 namespace Mono.CSharp {
+       public class VarianceDecl
+       {
+               public VarianceDecl (Variance variance, Location loc)
+               {
+                       this.Variance = variance;
+                       this.Location = loc;
+               }
+
+               public Variance Variance { get; private set; }
+               public Location Location { get; private set; }
+
+               public static Variance CheckTypeVariance (TypeSpec t, Variance expected, IMemberContext member)
+               {
+                       var tp = t as TypeParameterSpec;
+                       if (tp != null) {
+                               var v = tp.Variance;
+                               if (expected == Variance.None && v != expected ||
+                                       expected == Variance.Covariant && v == Variance.Contravariant ||
+                                       expected == Variance.Contravariant && v == Variance.Covariant) {
+                                       ((TypeParameter) tp.MemberDefinition).ErrorInvalidVariance (member, expected);
+                               }
+
+                               return expected;
+                       }
+
+                       if (t.TypeArguments.Length > 0) {
+                               var targs_definition = t.MemberDefinition.TypeParameters;
+                               TypeSpec[] targs = TypeManager.GetTypeArguments (t);
+                               for (int i = 0; i < targs.Length; ++i) {
+                                       var v = targs_definition[i].Variance;
+                                       CheckTypeVariance (targs[i], (Variance) ((int) v * (int) expected), member);
+                               }
+
+                               return expected;
+                       }
+
+                       var ac = t as ArrayContainer;
+                       if (ac != null)
+                               return CheckTypeVariance (ac.Element, expected, member);
+
+                       return Variance.None;
+               }
+       }
+
        public enum Variance
        {
                //
@@ -73,9 +117,9 @@ namespace Mono.CSharp {
        //
        public class Constraints
        {
-               SimpleMemberName tparam;
-               List<FullNamedExpression> constraints;
-               Location loc;
+               readonly SimpleMemberName tparam;
+               readonly List<FullNamedExpression> constraints;
+               readonly Location loc;
                bool resolved;
                bool resolving;
                
@@ -235,7 +279,7 @@ namespace Mono.CSharp {
                                        // is valid with respect to T
                                        //
                                        if (tp.IsMethodTypeParameter) {
-                                               TypeManager.CheckTypeVariance (type, Variance.Contravariant, context);
+                                               VarianceDecl.CheckTypeVariance (type, Variance.Contravariant, context);
                                        }
 
                                        var tp_def = constraint_tp.MemberDefinition as TypeParameter;
@@ -312,7 +356,7 @@ namespace Mono.CSharp {
                                if (type.IsSealed || !type.IsClass) {
                                        context.Module.Compiler.Report.Error (701, loc,
                                                "`{0}' is not a valid constraint. A constraint must be an interface, a non-sealed class or a type parameter",
-                                               TypeManager.CSharpName (type));
+                                               type.GetSignatureForError ());
                                        continue;
                                }
 
@@ -354,28 +398,30 @@ namespace Mono.CSharp {
        //
        public class TypeParameter : MemberCore, ITypeDefinition
        {
-               static readonly string[] attribute_target = new string [] { "type parameter" };
+               static readonly string[] attribute_target = { "type parameter" };
                
                Constraints constraints;
                GenericTypeParameterBuilder builder;
-               TypeParameterSpec spec;
+               readonly TypeParameterSpec spec;
 
-               public TypeParameter (int index, MemberName name, Constraints constraints, Attributes attrs, Variance variance)
+               public TypeParameter (int index, MemberName name, Constraints constraints, Attributes attrs, Variance Variance)
                        : base (null, name, attrs)
                {
                        this.constraints = constraints;
-                       this.spec = new TypeParameterSpec (null, index, this, SpecialConstraint.None, variance, null);
+                       this.spec = new TypeParameterSpec (null, index, this, SpecialConstraint.None, Variance, null);
                }
 
                //
                // Used by parser
                //
-               public TypeParameter (MemberName name, Attributes attrs, Variance variance)
+               public TypeParameter (MemberName name, Attributes attrs, VarianceDecl variance)
                        : base (null, name, attrs)
                {
-                       this.spec = new TypeParameterSpec (null, -1, this, SpecialConstraint.None, variance, null);
+                       var var = variance == null ? Variance.None : variance.Variance;
+                       this.spec = new TypeParameterSpec (null, -1, this, SpecialConstraint.None, var, null);
+                       this.VarianceDecl = variance;
                }
-
+               
                public TypeParameter (TypeParameterSpec spec, TypeSpec parentSpec, MemberName name, Attributes attrs)
                        : base (null, name, attrs)
                {
@@ -385,7 +431,7 @@ namespace Mono.CSharp {
                                TypeArguments = spec.TypeArguments
                        };
                }
-
+               
                #region Properties
 
                public override AttributeTargets AttributeTargets {
@@ -482,6 +528,8 @@ namespace Mono.CSharp {
                        }
                }
 
+               public VarianceDecl VarianceDecl { get; private set; }
+
                #endregion
 
                //
@@ -489,7 +537,7 @@ namespace Mono.CSharp {
                //
                // If partial type parameters constraints are not null and we don't
                // already have constraints they become our constraints. If we already
-               // have constraints, we must check that they're the same.
+               // have constraints, we must check that they're same.
                //
                public bool AddPartialConstraints (TypeDefinition part, TypeParameter tp)
                {
@@ -511,7 +559,7 @@ namespace Mono.CSharp {
 
                        // Copy constraint from resolved part to partial container
                        spec.SpecialConstraint = tp.spec.SpecialConstraint;
-                       spec.Interfaces = tp.spec.Interfaces;
+                       spec.InterfacesDefined = tp.spec.InterfacesDefined;
                        spec.TypeArguments = tp.spec.TypeArguments;
                        spec.BaseType = tp.spec.BaseType;
                        
@@ -545,15 +593,19 @@ namespace Mono.CSharp {
                // with SRE (by calling `DefineGenericParameters()' on the TypeBuilder /
                // MethodBuilder).
                //
-               public void Define (GenericTypeParameterBuilder type, TypeSpec declaringType, TypeContainer parent)
+               public void Create (TypeSpec declaringType, TypeContainer parent)
                {
                        if (builder != null)
                                throw new InternalErrorException ();
 
                        // Needed to get compiler reference
                        this.Parent = parent;
-                       this.builder = type;
                        spec.DeclaringType = declaringType;
+               }
+
+               public void Define (GenericTypeParameterBuilder type)
+               {
+                       this.builder = type;
                        spec.SetMetaInfo (type);
                }
 
@@ -579,8 +631,21 @@ namespace Mono.CSharp {
                        if (spec.InterfacesDefined != null)
                                builder.SetInterfaceConstraints (spec.InterfacesDefined.Select (l => l.GetMetaInfo ()).ToArray ());
 
-                       if (spec.TypeArguments != null)
-                               builder.SetInterfaceConstraints (spec.TypeArguments.Select (l => l.GetMetaInfo ()).ToArray ());
+                       if (spec.TypeArguments != null) {
+                               var meta_constraints = new List<MetaType> (spec.TypeArguments.Length);
+                               foreach (var c in spec.TypeArguments) {
+                                       //
+                                       // Inflated type parameters can collide with special constraint types, don't
+                                       // emit any such type parameter.
+                                       //
+                                       if (c.BuiltinType == BuiltinTypeSpec.Type.Object || c.BuiltinType == BuiltinTypeSpec.Type.ValueType)
+                                               continue;
+
+                                       meta_constraints.Add (c.GetMetaInfo ());
+                               }
+
+                               builder.SetInterfaceConstraints (meta_constraints.ToArray ());
+                       }
 
                        builder.SetGenericParameterAttributes (attr);
                }
@@ -776,6 +841,8 @@ namespace Mono.CSharp {
                                                                }
                                                        }
                                                }
+                                       } else if (ifaces_defined == null) {
+                                               ifaces_defined = ifaces == null ? TypeSpec.EmptyTypes : ifaces.ToArray ();
                                        }
 
                                        //
@@ -793,9 +860,6 @@ namespace Mono.CSharp {
                                                }
                                        }
 
-                                       if (ifaces_defined == null)
-                                               ifaces_defined = ifaces == null ? TypeSpec.EmptyTypes : ifaces.ToArray ();
-
                                        state |= StateFlags.InterfacesExpanded;
                                }
 
@@ -809,10 +873,7 @@ namespace Mono.CSharp {
                public TypeSpec[] InterfacesDefined {
                        get {
                                if (ifaces_defined == null) {
-                                       if (ifaces == null)
-                                               return null;
-
-                                       ifaces_defined = ifaces.ToArray ();
+                                       ifaces_defined = ifaces == null ? TypeSpec.EmptyTypes : ifaces.ToArray ();
                                }
 
                                return ifaces_defined.Length == 0 ? null : ifaces_defined;
@@ -1186,6 +1247,8 @@ namespace Mono.CSharp {
                                tps.ifaces_defined = new TypeSpec[defined.Length];
                                for (int i = 0; i < defined.Length; ++i)
                                        tps.ifaces_defined [i] = inflator.Inflate (defined[i]);
+                       } else if (ifaces_defined == TypeSpec.EmptyTypes) {
+                               tps.ifaces_defined = TypeSpec.EmptyTypes;
                        }
 
                        var ifaces = Interfaces;
@@ -1193,6 +1256,7 @@ namespace Mono.CSharp {
                                tps.ifaces = new List<TypeSpec> (ifaces.Count);
                                for (int i = 0; i < ifaces.Count; ++i)
                                        tps.ifaces.Add (inflator.Inflate (ifaces[i]));
+                               tps.state |= StateFlags.InterfacesExpanded;
                        }
 
                        if (targs != null) {
@@ -1205,6 +1269,10 @@ namespace Mono.CSharp {
                public override MemberSpec InflateMember (TypeParameterInflator inflator)
                {
                        var tps = (TypeParameterSpec) MemberwiseClone ();
+#if DEBUG
+                       tps.ID += 1000000;
+#endif
+
                        InflateConstraints (inflator, tps);
                        return tps;
                }
@@ -1377,6 +1445,9 @@ namespace Mono.CSharp {
                                return ac;
                        }
 
+                       if (type.Kind == MemberKind.MissingType)
+                               return type;
+
                        //
                        // When inflating a nested type, inflate its parent first
                        // in case it's using same type parameters (was inflated within the type)
@@ -1474,6 +1545,7 @@ namespace Mono.CSharp {
        {
                readonly TypeParameters mvar;
                readonly TypeParameters var;
+               readonly TypeParameterSpec[] src;
                Dictionary<TypeSpec, TypeSpec> mutated_typespec;
 
                public TypeParameterMutator (TypeParameters mvar, TypeParameters var)
@@ -1485,6 +1557,15 @@ namespace Mono.CSharp {
                        this.var = var;
                }
 
+               public TypeParameterMutator (TypeParameterSpec[] srcVar, TypeParameters destVar)
+               {
+                       if (srcVar.Length != destVar.Count)
+                               throw new ArgumentException ();
+
+                       this.src = srcVar;
+                       this.var = destVar;
+               }
+
                #region Properties
 
                public TypeParameters MethodTypeParameters {
@@ -1524,9 +1605,16 @@ namespace Mono.CSharp {
 
                public TypeParameterSpec Mutate (TypeParameterSpec tp)
                {
-                       for (int i = 0; i < mvar.Count; ++i) {
-                               if (mvar[i].Type == tp)
-                                       return var[i].Type;
+                       if (mvar != null) {
+                               for (int i = 0; i < mvar.Count; ++i) {
+                                       if (mvar[i].Type == tp)
+                                               return var[i].Type;
+                               }
+                       } else {
+                               for (int i = 0; i < src.Length; ++i) {
+                                       if (src[i] == tp)
+                                               return var[i].Type;
+                               }
                        }
 
                        return tp;
@@ -1642,7 +1730,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override bool IsGenericIterateInterface {
+               public override bool IsArrayGenericInterface {
                        get {
                                return (open_type.state & StateFlags.GenericIterateInterface) != 0;
                        }
@@ -1699,7 +1787,7 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               TypeParameterInflator CreateLocalInflator (IModuleContext context)
+               public TypeParameterInflator CreateLocalInflator (IModuleContext context)
                {
                        TypeParameterSpec[] tparams_full;
                        TypeSpec[] targs_full = targs;
@@ -1751,7 +1839,7 @@ namespace Mono.CSharp {
                        return new TypeParameterInflator (context, this, tparams_full, targs_full);
                }
 
-               MetaType CreateMetaInfo (TypeParameterMutator mutator)
+               MetaType CreateMetaInfo ()
                {
                        //
                        // Converts nested type arguments into right order
@@ -1801,7 +1889,7 @@ namespace Mono.CSharp {
                public override MetaType GetMetaInfo ()
                {
                        if (info == null)
-                               info = CreateMetaInfo (null);
+                               info = CreateMetaInfo ();
 
                        return info;
                }
@@ -2159,13 +2247,13 @@ namespace Mono.CSharp {
                        names.AddRange (tparams.names);
                }
 
-               public void Define (GenericTypeParameterBuilder[] buiders, TypeSpec declaringType, int parentOffset, TypeContainer parent)
+               public void Create (TypeSpec declaringType, int parentOffset, TypeContainer parent)
                {
                        types = new TypeParameterSpec[Count];
                        for (int i = 0; i < types.Length; ++i) {
                                var tp = names[i];
 
-                               tp.Define (buiders[i + parentOffset], declaringType, parent);
+                               tp.Create (declaringType, parent);
                                types[i] = tp.Type;
                                types[i].DeclaredPosition = i + parentOffset;
 
@@ -2175,6 +2263,14 @@ namespace Mono.CSharp {
                        }
                }
 
+               public void Define (GenericTypeParameterBuilder[] builders)
+               {
+                       for (int i = 0; i < types.Length; ++i) {
+                               var tp = names[i];
+                               tp.Define (builders [types [i].DeclaredPosition]);
+                       }
+               }
+
                public TypeParameter this[int index] {
                        get {
                                return names [index];
@@ -2214,6 +2310,44 @@ namespace Mono.CSharp {
                        return sb.ToString ();
                }
 
+
+               public void CheckPartialConstraints (Method part)
+               {
+                       var partTypeParameters = part.CurrentTypeParameters;
+
+                       for (int i = 0; i < Count; i++) {
+                               var tp_a = names[i];
+                               var tp_b = partTypeParameters [i];
+                               if (tp_a.Constraints == null) {
+                                       if (tp_b.Constraints == null)
+                                               continue;
+                               } else if (tp_b.Constraints != null && tp_a.Type.HasSameConstraintsDefinition (tp_b.Type)) {
+                                       continue;
+                               }
+
+                               part.Compiler.Report.SymbolRelatedToPreviousError (this[i].CurrentMemberDefinition.Location, "");
+                               part.Compiler.Report.Error (761, part.Location,
+                                       "Partial method declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
+                                       part.GetSignatureForError (), partTypeParameters[i].GetSignatureForError ());
+                       }
+               }
+
+               public void UpdateConstraints (TypeDefinition part)
+               {
+                       var partTypeParameters = part.MemberName.TypeParameters;
+
+                       for (int i = 0; i < Count; i++) {
+                               var tp = names [i];
+                               if (tp.AddPartialConstraints (part, partTypeParameters [i]))
+                                       continue;
+
+                               part.Compiler.Report.SymbolRelatedToPreviousError (this[i].CurrentMemberDefinition);
+                               part.Compiler.Report.Error (265, part.Location,
+                                       "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
+                                       part.GetSignatureForError (), tp.GetSignatureForError ());
+                       }
+               }
+
                public void VerifyClsCompliance ()
                {
                        foreach (var tp in names) {
@@ -2244,7 +2378,7 @@ namespace Mono.CSharp {
 
                public override string GetSignatureForError ()
                {
-                       return TypeManager.CSharpName (type);
+                       return type.GetSignatureForError ();
                }
 
                public override TypeSpec ResolveAsType (IMemberContext mc)
@@ -2392,7 +2526,7 @@ namespace Mono.CSharp {
                                if (mc != null) {
                                        mc.Module.Compiler.Report.Error (452, loc,
                                                "The type `{0}' must be a reference type in order to use it as type parameter `{1}' in the generic type or method `{2}'",
-                                               TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ());
+                                               atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError ());
                                }
 
                                return false;
@@ -2402,7 +2536,7 @@ namespace Mono.CSharp {
                                if (mc != null) {
                                        mc.Module.Compiler.Report.Error (453, loc,
                                                "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}'",
-                                               TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ());
+                                               atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError ());
                                }
 
                                return false;
@@ -2425,8 +2559,8 @@ namespace Mono.CSharp {
                        //
                        // Check the interfaces constraints
                        //
-                       if (tparam.Interfaces != null) {
-                               foreach (TypeSpec iface in tparam.Interfaces) {
+                       if (tparam.InterfacesDefined != null) {
+                               foreach (TypeSpec iface in tparam.InterfacesDefined) {
                                        if (!CheckConversion (mc, context, atype, tparam, iface, loc)) {
                                                if (mc == null)
                                                        return false;
@@ -2463,7 +2597,7 @@ namespace Mono.CSharp {
                                        mc.Module.Compiler.Report.SymbolRelatedToPreviousError (atype);
                                        mc.Module.Compiler.Report.Error (310, loc,
                                                "The type `{0}' must have a public parameterless constructor in order to use it as parameter `{1}' in the generic type or method `{2}'",
-                                               TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ());
+                                               atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError ());
                                }
                                return false;
                        }
@@ -2569,40 +2703,6 @@ namespace Mono.CSharp {
                }
        }
 
-       public partial class TypeManager
-       {
-               public static Variance CheckTypeVariance (TypeSpec t, Variance expected, IMemberContext member)
-               {
-                       var tp = t as TypeParameterSpec;
-                       if (tp != null) {
-                               Variance v = tp.Variance;
-                               if (expected == Variance.None && v != expected ||
-                                       expected == Variance.Covariant && v == Variance.Contravariant ||
-                                       expected == Variance.Contravariant && v == Variance.Covariant) {
-                                       ((TypeParameter)tp.MemberDefinition).ErrorInvalidVariance (member, expected);
-                               }
-
-                               return expected;
-                       }
-
-                       if (t.TypeArguments.Length > 0) {
-                               var targs_definition = t.MemberDefinition.TypeParameters;
-                               TypeSpec[] targs = GetTypeArguments (t);
-                               for (int i = 0; i < targs.Length; ++i) {
-                                       Variance v = targs_definition[i].Variance;
-                                       CheckTypeVariance (targs[i], (Variance) ((int)v * (int)expected), member);
-                               }
-
-                               return expected;
-                       }
-
-                       if (t.IsArray)
-                               return CheckTypeVariance (GetElementType (t), expected, member);
-
-                       return Variance.None;
-               }
-       }
-
        //
        // Implements C# type inference
        //
@@ -2683,7 +2783,7 @@ namespace Mono.CSharp {
                                //
                                AnonymousMethodExpression am = a.Expr as AnonymousMethodExpression;
                                if (am != null) {
-                                       if (am.ExplicitTypeInference (ec, tic, method_parameter))
+                                       if (am.ExplicitTypeInference (tic, method_parameter))
                                                --score; 
                                        continue;
                                }
@@ -2749,7 +2849,7 @@ namespace Mono.CSharp {
                                var mi = Delegate.GetInvokeMethod (t_i);
                                TypeSpec rtype = mi.ReturnType;
 
-                               if (tic.IsReturnTypeNonDependent (ec, mi, rtype)) {
+                               if (tic.IsReturnTypeNonDependent (mi, rtype)) {
                                        // It can be null for default arguments
                                        if (arguments[i] == null)
                                                continue;
@@ -2848,15 +2948,20 @@ namespace Mono.CSharp {
 
                public void AddCommonTypeBound (TypeSpec type)
                {
-                       AddToBounds (new BoundInfo (type, BoundKind.Lower), 0);
+                       AddToBounds (new BoundInfo (type, BoundKind.Lower), 0, false);
+               }
+
+               public void AddCommonTypeBoundAsync (TypeSpec type)
+               {
+                       AddToBounds (new BoundInfo (type, BoundKind.Lower), 0, true);
                }
 
-               void AddToBounds (BoundInfo bound, int index)
+               void AddToBounds (BoundInfo bound, int index, bool voidAllowed)
                {
                        //
                        // Some types cannot be used as type arguments
                        //
-                       if (bound.Type.Kind == MemberKind.Void || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
+                       if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
                                bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod)
                                return;
 
@@ -2930,7 +3035,7 @@ namespace Mono.CSharp {
                        if (pos == -1)
                                return 0;
 
-                       AddToBounds (new BoundInfo (u, BoundKind.Exact), pos);
+                       AddToBounds (new BoundInfo (u, BoundKind.Exact), pos, false);
                        return 1;
                }
 
@@ -3037,87 +3142,100 @@ namespace Mono.CSharp {
                        }
 
                        //
-                       // Determines a unique type from which there is
-                       // a standard implicit conversion to all the other
-                       // candidate types.
+                       // The set of candidate types Uj starts out as the set of
+                       // all types in the set of bounds for Xi
                        //
-                       TypeSpec best_candidate = null;
-                       int cii;
-                       int candidates_count = candidates.Count;
-                       for (int ci = 0; ci < candidates_count; ++ci) {
-                               BoundInfo bound = candidates [ci];
-                               for (cii = 0; cii < candidates_count; ++cii) {
-                                       if (cii == ci)
-                                               continue;
+                       var applicable = new bool [candidates.Count];
+                       for (int ci = 0; ci < applicable.Length; ++ci)
+                               applicable [ci] = true;
+
+                       for (int ci = 0; ci < applicable.Length; ++ci) {
+                               var bound = candidates [ci];
+                               int cii = 0;
+
+                               switch (bound.Kind) {
+                               case BoundKind.Exact:
+                                       for (; cii != applicable.Length; ++cii) {
+                                               if (ci == cii)
+                                                       continue;
 
-                                       BoundInfo cbound = candidates[cii];
-                                       
-                                       // Same type parameters with different bounds
-                                       if (cbound.Type == bound.Type) {
-                                               if (bound.Kind != BoundKind.Exact)
-                                                       bound = cbound;
+                                               if (!applicable[cii])
+                                                       break;
 
-                                               continue;
+                                               //
+                                               // For each exact bound U of Xi all types Uj which are not identical
+                                               // to U are removed from the candidate set
+                                               //
+                                               if (candidates [cii].Type != bound.Type)
+                                                       applicable[cii] = false;
                                        }
 
-                                       if (bound.Kind == BoundKind.Exact || cbound.Kind == BoundKind.Exact) {
-                                               if (cbound.Kind == BoundKind.Lower) {
-                                                       if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) {
-                                                               break;
-                                                       }
-
+                                       break;
+                               case BoundKind.Lower:
+                                       for (; cii != applicable.Length; ++cii) {
+                                               if (ci == cii)
                                                        continue;
-                                               }
-                                               if (cbound.Kind == BoundKind.Upper) {
-                                                       if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
-                                                               break;
-                                                       }
 
-                                                       continue;
+                                               if (!applicable[cii])
+                                                       break;
+
+                                               //
+                                               // For each lower bound U of Xi all types Uj to which there is not an implicit conversion
+                                               // from U are removed from the candidate set
+                                               //
+                                               if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), candidates [cii].Type)) {
+                                                       applicable[cii] = false;
                                                }
-                                               
-                                               if (bound.Kind != BoundKind.Exact) {
-                                                       if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
-                                                               break;
-                                                       }
+                                       }
+
+                                       break;
 
-                                                       bound = cbound;
+                               case BoundKind.Upper:
+                                       for (; cii != applicable.Length; ++cii) {
+                                               if (ci == cii)
                                                        continue;
-                                               }
-                                               
-                                               break;
+
+                                               if (!applicable[cii])
+                                                       break;
+
+                                               //
+                                               // For each upper bound U of Xi all types Uj from which there is not an implicit conversion
+                                               // to U are removed from the candidate set
+                                               //
+                                               if (!Convert.ImplicitConversionExists (ec, candidates[cii].GetTypeExpression (), bound.Type))
+                                                       applicable[cii] = false;
                                        }
 
-                                       if (bound.Kind == BoundKind.Lower) {
-                                               if (cbound.Kind == BoundKind.Lower) {
-                                                       if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) {
-                                                               break;
-                                                       }
-                                               } else {
-                                                       if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
-                                                               break;
-                                                       }
+                                       break;
+                               }
+                       }
 
-                                                       bound = cbound;
-                                               }
+                       TypeSpec best_candidate = null;
+                       for (int ci = 0; ci < applicable.Length; ++ci) {
+                               if (!applicable[ci])
+                                       continue;
+
+                               var bound = candidates [ci];
+                               if (bound.Type == best_candidate)
+                                       continue;
 
+                               int cii = 0;
+                               for (; cii < applicable.Length; ++cii) {
+                                       if (ci == cii)
                                                continue;
-                                       }
 
-                                       if (bound.Kind == BoundKind.Upper) {
-                                               if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
-                                                       break;
-                                               }
-                                       } else {
-                                               throw new NotImplementedException ("variance conversion");
-                                       }
+                                       if (!applicable[cii])
+                                               continue;
+
+                                       if (!Convert.ImplicitConversionExists (ec, candidates[cii].GetTypeExpression (), bound.Type))
+                                               break;
                                }
 
-                               if (cii != candidates_count)
+                               if (cii != applicable.Length)
                                        continue;
 
                                //
-                               // We already have the best candidate, break if thet are different
+                               // We already have the best candidate, break if it's different (non-unique)
                                //
                                // Dynamic is never ambiguous as we prefer dynamic over other best candidate types
                                //
@@ -3196,8 +3314,13 @@ namespace Mono.CSharp {
                // Tests whether all delegate input arguments are fixed and generic output type
                // requires output type inference 
                //
-               public bool IsReturnTypeNonDependent (ResolveContext ec, MethodSpec invoke, TypeSpec returnType)
+               public bool IsReturnTypeNonDependent (MethodSpec invoke, TypeSpec returnType)
                {
+                       AParametersCollection d_parameters = invoke.Parameters;
+
+                       if (d_parameters.IsEmpty)
+                               return true;
+
                        while (returnType.IsArray)
                                returnType = ((ArrayContainer) returnType).Element;
 
@@ -3205,11 +3328,6 @@ namespace Mono.CSharp {
                                if (IsFixed (returnType))
                                    return false;
                        } else if (TypeManager.IsGenericType (returnType)) {
-                               if (returnType.IsDelegate) {
-                                       invoke = Delegate.GetInvokeMethod (returnType);
-                                       return IsReturnTypeNonDependent (ec, invoke, invoke.ReturnType);
-                               }
-                                       
                                TypeSpec[] g_args = TypeManager.GetTypeArguments (returnType);
                                
                                // At least one unfixed return type has to exist 
@@ -3220,10 +3338,9 @@ namespace Mono.CSharp {
                        }
 
                        // All generic input arguments have to be fixed
-                       AParametersCollection d_parameters = invoke.Parameters;
                        return AllTypesAreFixed (d_parameters.Types);
                }
-               
+
                bool IsFixed (TypeSpec type)
                {
                        return IsUnfixed (type) == -1;
@@ -3262,7 +3379,7 @@ namespace Mono.CSharp {
                        // If V is one of the unfixed type arguments
                        int pos = IsUnfixed (v);
                        if (pos != -1) {
-                               AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos);
+                               AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos, false);
                                return 1;
                        }                       
 
@@ -3280,7 +3397,7 @@ namespace Mono.CSharp {
                                        return LowerBoundInference (u_ac.Element, v_ac.Element, inversed);
                                }
 
-                               if (u_ac.Rank != 1 || !v.IsGenericIterateInterface)
+                               if (u_ac.Rank != 1 || !v.IsArrayGenericInterface)
                                        return 0;
 
                                var v_i = TypeManager.GetTypeArguments (v) [0];
@@ -3430,7 +3547,7 @@ namespace Mono.CSharp {
                                var invoke = Delegate.GetInvokeMethod (t);
                                TypeSpec rtype = invoke.ReturnType;
 
-                               if (!rtype.IsGenericParameter && !TypeManager.IsGenericType (rtype))
+                               if (!IsReturnTypeNonDependent (invoke, rtype))
                                        return 0;
 
                                // LAMESPEC: Standard does not specify that all methodgroup arguments
@@ -3443,14 +3560,11 @@ namespace Mono.CSharp {
                                        if (inflated == null)
                                                return 0;
 
-                                       if (IsUnfixed (inflated) >= 0)
-                                               return 0;
-
                                        param_types[i] = inflated;
                                }
 
                                MethodGroupExpr mg = (MethodGroupExpr) e;
-                               Arguments args = DelegateCreation.CreateDelegateMethodArguments (invoke.Parameters, param_types, e.Location);
+                               Arguments args = DelegateCreation.CreateDelegateMethodArguments (ec, invoke.Parameters, param_types, e.Location);
                                mg = mg.OverloadResolve (ec, ref args, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly);
                                if (mg == null)
                                        return 0;