Nothing to see here
[mono.git] / mcs / mcs / generic.cs
index 27a2b9399d73b1e12abdd4b2e690c8e24010bc32..fa210289ecf3efe896b27a4421e47b52f5cfb926 100644 (file)
@@ -182,7 +182,7 @@ namespace Mono.CSharp {
                        if (resolved)
                                return true;
 
-                       iface_constraints = new ArrayList ();
+                       iface_constraints = new ArrayList (2);  // TODO: Too expensive allocation
                        type_param_constraints = new ArrayList ();
 
                        foreach (object obj in constraints) {
@@ -256,11 +256,10 @@ namespace Mono.CSharp {
                                        type_param_constraints.Add (expr);
                                else if (expr.IsInterface)
                                        iface_constraints.Add (expr);
-                               else if (class_constraint != null) {
+                               else if (class_constraint != null || iface_constraints.Count != 0) {
                                        Report.Error (406, loc,
-                                                     "`{0}': the class constraint for `{1}' " +
-                                                     "must come before any other constraints.",
-                                                     expr.GetSignatureForError (), name);
+                                               "The class type constraint `{0}' must be listed before any other constraints. Consider moving type constraint to the beginning of the constraint list",
+                                               expr.GetSignatureForError ());
                                        return false;
                                } else if (HasReferenceTypeConstraint || HasValueTypeConstraint) {
                                        Report.Error (450, loc, "`{0}': cannot specify both " +
@@ -345,26 +344,52 @@ namespace Mono.CSharp {
                        else
                                effective_base_type = TypeManager.object_type;
 
+                       if ((attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
+                               attrs |= GenericParameterAttributes.DefaultConstructorConstraint;
+
                        resolved = true;
                        return true;
                }
 
-               bool CheckTypeParameterConstraints (TypeParameter tparam, Hashtable seen)
+               bool CheckTypeParameterConstraints (TypeParameter tparam, ref TypeExpr prevConstraint, ArrayList seen)
                {
-                       seen.Add (tparam, true);
+                       seen.Add (tparam);
 
                        Constraints constraints = tparam.Constraints;
                        if (constraints == null)
                                return true;
 
                        if (constraints.HasValueTypeConstraint) {
-                               Report.Error (456, loc, "Type parameter `{0}' has " +
-                                             "the `struct' constraint, so it cannot " +
-                                             "be used as a constraint for `{1}'",
-                                             tparam.Name, name);
+                               Report.Error (456, loc,
+                                       "Type parameter `{0}' has the `struct' constraint, so it cannot be used as a constraint for `{1}'",
+                                       tparam.Name, name);
                                return false;
                        }
 
+                       //
+                       //  Checks whether there are no conflicts between type parameter constraints
+                       //
+                       //   class Foo<T, U>
+                       //      where T : A
+                       //      where U : A, B  // A and B are not convertible
+                       //
+                       if (constraints.HasClassConstraint) {
+                               if (prevConstraint != null) {
+                                       Type t2 = constraints.ClassConstraint;
+                                       TypeExpr e2 = constraints.class_constraint;
+
+                                       if (!Convert.ImplicitReferenceConversionExists (prevConstraint, t2) &&
+                                               !Convert.ImplicitReferenceConversionExists (e2, prevConstraint.Type)) {
+                                               Report.Error (455, loc,
+                                                       "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'",
+                                                       name, TypeManager.CSharpName (prevConstraint.Type), TypeManager.CSharpName (t2));
+                                               return false;
+                                       }
+                               }
+
+                               prevConstraint = constraints.class_constraint;
+                       }
+
                        if (constraints.type_param_constraints == null)
                                return true;
 
@@ -376,7 +401,7 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
-                               if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
+                               if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prevConstraint, seen))
                                        return false;
                        }
 
@@ -402,10 +427,14 @@ namespace Mono.CSharp {
                                        return false;
                        }
 
-                       foreach (TypeParameterExpr expr in type_param_constraints) {
-                               Hashtable seen = new Hashtable ();
-                               if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
-                                       return false;
+                       if (type_param_constraints.Count != 0) {
+                               ArrayList seen = new ArrayList ();
+                               TypeExpr prev_constraint = class_constraint;
+                               foreach (TypeParameterExpr expr in type_param_constraints) {
+                                       if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prev_constraint, seen))
+                                               return false;
+                                       seen.Clear ();
+                               }
                        }
 
                        for (int i = 0; i < iface_constraints.Count; ++i) {
@@ -425,66 +454,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               /// <summary>
-               ///   Check whether there are no conflicts in our type parameter constraints.
-               ///
-               ///   This is an example:
-               ///
-               ///   class Foo<T,U>
-               ///      where T : class
-               ///      where U : T, struct
-               /// </summary>
-               public bool CheckDependencies ()
-               {
-                       foreach (TypeParameterExpr expr in type_param_constraints) {
-                               if (!CheckDependencies (expr.TypeParameter))
-                                       return false;
-                       }
-
-                       return true;
-               }
-
-               bool CheckDependencies (TypeParameter tparam)
-               {
-                       Constraints constraints = tparam.Constraints;
-                       if (constraints == null)
-                               return true;
-
-                       if (HasValueTypeConstraint && constraints.HasClassConstraint) {
-                               Report.Error (455, loc, "Type parameter `{0}' inherits " +
-                                             "conflicting constraints `{1}' and `{2}'",
-                                             name, TypeManager.CSharpName (constraints.ClassConstraint),
-                                             "System.ValueType");
-                               return false;
-                       }
-
-                       if (HasClassConstraint && constraints.HasClassConstraint) {
-                               Type t1 = ClassConstraint;
-                               TypeExpr e1 = class_constraint;
-                               Type t2 = constraints.ClassConstraint;
-                               TypeExpr e2 = constraints.class_constraint;
-
-                               if (!Convert.ImplicitReferenceConversionExists (e1, t2) &&
-                                   !Convert.ImplicitReferenceConversionExists (e2, t1)) {
-                                       Report.Error (455, loc,
-                                                     "Type parameter `{0}' inherits " +
-                                                     "conflicting constraints `{1}' and `{2}'",
-                                                     name, TypeManager.CSharpName (t1), TypeManager.CSharpName (t2));
-                                       return false;
-                               }
-                       }
-
-                       if (constraints.type_param_constraints == null)
-                               return true;
-
-                       foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
-                               if (!CheckDependencies (expr.TypeParameter))
-                                       return false;
-                       }
-
-                       return true;
-               }
-
                public override GenericParameterAttributes Attributes {
                        get { return attrs; }
                }
@@ -535,7 +504,7 @@ namespace Mono.CSharp {
                ///   method.  To do that, we're called on each of the implementing method's
                ///   type parameters.
                /// </summary>
-               public bool CheckInterfaceMethod (GenericConstraints gc)
+               public bool AreEqual (GenericConstraints gc)
                {
                        if (gc.Attributes != attrs)
                                return false;
@@ -610,7 +579,6 @@ namespace Mono.CSharp {
                DeclSpace decl;
                GenericConstraints gc;
                Constraints constraints;
-               Location loc;
                GenericTypeParameterBuilder type;
                MemberCache member_cache;
 
@@ -621,7 +589,6 @@ namespace Mono.CSharp {
                        this.name = name;
                        this.decl = decl;
                        this.constraints = constraints;
-                       this.loc = loc;
                }
 
                public GenericConstraints GenericConstraints {
@@ -731,7 +698,7 @@ namespace Mono.CSharp {
 
                        if (implementing != null) {
                                if (is_override && (constraints != null)) {
-                                       Report.Error (460, loc,
+                                       Report.Error (460, Location,
                                                "`{0}': Cannot specify constraints for overrides or explicit interface implementation methods",
                                                TypeManager.CSharpSignature (builder));
                                        return false;
@@ -752,7 +719,7 @@ namespace Mono.CSharp {
                                if (constraints != null) {
                                        if (temp_gc == null)
                                                ok = false;
-                                       else if (!constraints.CheckInterfaceMethod (gc))
+                                       else if (!constraints.AreEqual (gc))
                                                ok = false;
                                } else {
                                        if (!is_override && (temp_gc != null))
@@ -763,7 +730,7 @@ namespace Mono.CSharp {
                                        Report.SymbolRelatedToPreviousError (implementing);
 
                                        Report.Error (
-                                               425, loc, "The constraints for type " +
+                                               425, Location, "The constraints for type " +
                                                "parameter `{0}' of method `{1}' must match " +
                                                "the constraints for type parameter `{2}' " +
                                                "of interface method `{3}'. Consider using " +
@@ -787,8 +754,8 @@ namespace Mono.CSharp {
                        if (gc == null)
                                return true;
 
-                       if (gc.HasClassConstraint)
-                               type.SetBaseTypeConstraint (gc.ClassConstraint);
+                       if (gc.HasClassConstraint || gc.HasValueTypeConstraint)
+                               type.SetBaseTypeConstraint (gc.EffectiveBaseClass);
 
                        type.SetInterfaceConstraints (gc.InterfaceConstraints);
                        type.SetGenericParameterAttributes (gc.Attributes);
@@ -797,23 +764,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               /// <summary>
-               ///   Check whether there are no conflicts in our type parameter constraints.
-               ///
-               ///   This is an example:
-               ///
-               ///   class Foo<T,U>
-               ///      where T : class
-               ///      where U : T, struct
-               /// </summary>
-               public bool CheckDependencies ()
-               {
-                       if (constraints != null)
-                               return constraints.CheckDependencies ();
-
-                       return true;
-               }
-
                /// <summary>
                ///   This is called for each part of a partial generic type definition.
                ///
@@ -836,7 +786,7 @@ namespace Mono.CSharp {
                                return false;
 
                        if (constraints != null) 
-                               return constraints.CheckInterfaceMethod (new_constraints);
+                               return constraints.AreEqual (new_constraints);
 
                        constraints = new_constraints;
                        return true;
@@ -1047,7 +997,7 @@ namespace Mono.CSharp {
                                if (t == null)
                                        return null;
                                if (t.IsGenericParameter)
-                                       return dargs [t.GenericParameterPosition];
+                                       return t.GenericParameterPosition < dargs.Length ? dargs [t.GenericParameterPosition] : t;
                                if (t.IsGenericType) {
                                        Type[] args = t.GetGenericArguments ();
                                        Type[] inflated = new Type [args.Length];
@@ -1104,8 +1054,13 @@ namespace Mono.CSharp {
 
                protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
                {
-                       type = type_parameter.Type;
+                       throw new NotSupportedException ();
+               }
 
+               public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
+               {
+                       type = type_parameter.Type;
+                       eclass = ExprClass.TypeParameter;
                        return this;
                }
 
@@ -1129,7 +1084,6 @@ namespace Mono.CSharp {
                Type[] atypes;
                int dimension;
                bool has_type_args;
-               bool created;
                
                public TypeArguments (Location loc)
                {
@@ -1151,17 +1105,11 @@ namespace Mono.CSharp {
 
                public void Add (Expression type)
                {
-                       if (created)
-                               throw new InvalidOperationException ();
-
                        args.Add (type);
                }
 
                public void Add (TypeArguments new_args)
                {
-                       if (created)
-                               throw new InvalidOperationException ();
-
                        args.AddRange (new_args.args);
                }
 
@@ -1181,7 +1129,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
                                SimpleName sn = args [i] as SimpleName;
-                               if (sn != null) {
+                               if (sn != null && !sn.HasTypeArguments) {
                                        ret [i] = new TypeParameterName (sn.Name, null, sn.Location);
                                        continue;
                                }
@@ -1285,9 +1233,10 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
-                               if (te.Type.IsPointer) {
-                                       Report.Error (306, Location, "The type `{0}' may not be used " +
-                                                         "as a type argument", TypeManager.CSharpName (te.Type));
+                               if (te.Type.IsPointer || TypeManager.IsSpecialType (te.Type)) {
+                                       Report.Error (306, Location,
+                                               "The type `{0}' may not be used as a type argument",
+                                               TypeManager.CSharpName (te.Type));
                                        return false;
                                }
 
@@ -1381,7 +1330,7 @@ namespace Mono.CSharp {
 
                public override string GetSignatureForError ()
                {
-                       return TypeManager.RemoveGenericArity (gt.FullName) + "<" + args.GetSignatureForError () + ">";
+                       return TypeManager.CSharpName (type);
                }
 
                protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
@@ -1671,12 +1620,36 @@ namespace Mono.CSharp {
                        if (Convert.ImplicitStandardConversionExists (expr, ctype))
                                return true;
 
-                       Error_TypeMustBeConvertible (expr.Type, ctype, ptype);
+                       Report_SymbolRelatedToPreviousError ();
+                       Report.SymbolRelatedToPreviousError (expr.Type);
+
+                       if (TypeManager.IsNullableType (expr.Type) && ctype.IsInterface) {
+                               Report.Error (313, loc,
+                                       "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 of type `{3}'",
+                                       TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ptype),
+                                       GetSignatureForError (), TypeManager.CSharpName (ctype));
+                       } else {
+                               Report.Error (309, loc,
+                                       "The type `{0}' must be convertible to `{1}' in order to " +
+                                       "use it as parameter `{2}' in the generic type or method `{3}'",
+                                       TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ctype),
+                                       TypeManager.CSharpName (ptype), GetSignatureForError ());
+                       }
                        return false;
                }
 
-               bool HasDefaultConstructor (Type atype)
+               static bool HasDefaultConstructor (Type atype)
                {
+                       TypeParameter tparam = TypeManager.LookupTypeParameter (atype);
+                       if (tparam != null) {
+                               if (tparam.GenericConstraints == null)
+                                       return false;
+                                               
+                               return tparam.GenericConstraints.HasConstructorConstraint || 
+                                       tparam.GenericConstraints.HasValueTypeConstraint;
+                       }
+               
                        if (atype.IsAbstract)
                                return false;
 
@@ -1702,15 +1675,6 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       TypeParameter tparam = TypeManager.LookupTypeParameter (atype);
-                       if (tparam != null) {
-                               if (tparam.GenericConstraints == null)
-                                       return false;
-                                               
-                               return tparam.GenericConstraints.HasConstructorConstraint || 
-                                       tparam.GenericConstraints.HasValueTypeConstraint;
-                       }
-
                        MemberInfo [] list = TypeManager.MemberLookup (null, null, atype, MemberTypes.Constructor,
                                BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
                                ConstructorInfo.ConstructorName, null);
@@ -1719,7 +1683,7 @@ namespace Mono.CSharp {
                                return false;
 
                        foreach (MethodBase mb in list) {
-                               ParameterData pd = TypeManager.GetParameterData (mb);
+                               AParametersCollection pd = TypeManager.GetParameterData (mb);
                                if (pd.Count == 0)
                                        return true;
                        }
@@ -1730,17 +1694,6 @@ namespace Mono.CSharp {
                protected abstract string GetSignatureForError ();
                protected abstract void Report_SymbolRelatedToPreviousError ();
 
-               void Error_TypeMustBeConvertible (Type atype, Type gc, Type ptype)
-               {
-                       Report_SymbolRelatedToPreviousError ();
-                       Report.SymbolRelatedToPreviousError (atype);
-                       Report.Error (309, loc, 
-                                     "The type `{0}' must be convertible to `{1}' in order to " +
-                                     "use it as parameter `{2}' in the generic type or method `{3}'",
-                                     TypeManager.CSharpName (atype), TypeManager.CSharpName (gc),
-                                     TypeManager.CSharpName (ptype), GetSignatureForError ());
-               }
-
                public static bool CheckConstraints (EmitContext ec, MethodBase definition,
                                                     MethodBase instantiated, Location loc)
                {
@@ -1810,11 +1763,11 @@ namespace Mono.CSharp {
        /// </summary>
        public class GenericMethod : DeclSpace
        {
-               Expression return_type;
+               FullNamedExpression return_type;
                Parameters parameters;
 
                public GenericMethod (NamespaceEntry ns, DeclSpace parent, MemberName name,
-                                     Expression return_type, Parameters parameters)
+                                     FullNamedExpression return_type, Parameters parameters)
                        : base (ns, parent, name, null)
                {
                        this.return_type = return_type;
@@ -1839,7 +1792,7 @@ namespace Mono.CSharp {
                ///   Define and resolve the type parameters.
                ///   We're called from Method.Define().
                /// </summary>
-               public bool Define (MethodBuilder mb, ToplevelBlock block)
+               public bool Define (MethodBuilder mb)
                {
                        TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
                        string[] snames = new string [names.Length];
@@ -1886,11 +1839,8 @@ namespace Mono.CSharp {
                                            ec, mb, implementing, is_override))
                                        return false;
 
-                       bool ok = true;
-                       foreach (Parameter p in parameters.FixedParameters){
-                               if (!p.Resolve (ec))
-                                       ok = false;
-                       }
+                       bool ok = parameters.Resolve (ec);
+
                        if ((return_type != null) && (return_type.ResolveAsTypeTerminal (ec, false) == null))
                                ok = false;
 
@@ -1906,11 +1856,6 @@ namespace Mono.CSharp {
                                OptAttributes.Emit ();
                }
 
-               public override bool DefineMembers ()
-               {
-                       return true;
-               }
-
                public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
                                                        MemberFilter filter, object criteria)
                {
@@ -1946,6 +1891,8 @@ namespace Mono.CSharp {
 
        public partial class TypeManager
        {
+               static public Type activator_type;
+       
                public static TypeContainer LookupGenericTypeContainer (Type t)
                {
                        t = DropGenericTypeArguments (t);
@@ -2103,7 +2050,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Type inference.
                /// </summary>
-               public static bool InferTypeArguments (ParameterData apd,
+               public static bool InferTypeArguments (AParametersCollection apd,
                                                       ref MethodBase method)
                {
                        if (!TypeManager.IsGenericMethod (method))
@@ -2161,7 +2108,7 @@ namespace Mono.CSharp {
 
                public override Type[] InferDelegateArguments (MethodBase method)
                {
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        if (arg_count != pd.Count)
                                return null;
 
@@ -2172,7 +2119,7 @@ namespace Mono.CSharp {
                        Type[] arg_types = (Type[])arguments.ToArray (typeof (Type));
 
                        for (int i = 0; i < arg_count; i++) {
-                               param_types[i] = pd.ParameterType (i);
+                               param_types[i] = pd.Types [i];
                        }
 
                        if (!InferTypeArguments (param_types, arg_types, inferred_types))
@@ -2183,7 +2130,7 @@ namespace Mono.CSharp {
 
                public override Type[] InferMethodArguments (EmitContext ec, MethodBase method)
                {
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        Type[] method_generic_args = method.GetGenericArguments ();
                        Type [] inferred_types = new Type [method_generic_args.Length];
                        Type[] arg_types = new Type [pd.Count];
@@ -2197,12 +2144,12 @@ namespace Mono.CSharp {
                                if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
                                        continue;
 
-                               if (!TypeInferenceV2.UnifyType (pd.ParameterType (i), a.Type, inferred_types))
+                               if (!TypeInferenceV2.UnifyType (pd.Types [i], a.Type, inferred_types))
                                        return null;
                        }
 
                        if (pd.HasParams) {
-                               Type element_type = TypeManager.GetElementType (pd.ParameterType (a_count));
+                               Type element_type = TypeManager.GetElementType (pd.Types [a_count]);
                                for (int i = a_count; i < arg_count; i++) {
                                        Argument a = (Argument) arguments [i];
                                        if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
@@ -2344,7 +2291,7 @@ namespace Mono.CSharp {
 
                public override Type[] InferDelegateArguments (MethodBase method)
                {
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        if (arg_count != pd.Count)
                                return null;
 
@@ -2374,7 +2321,7 @@ namespace Mono.CSharp {
                        if (!context.UnfixedVariableExists)
                                return Type.EmptyTypes;
 
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        if (!InferInPhases (ec, context, pd))
                                return null;
 
@@ -2384,7 +2331,7 @@ namespace Mono.CSharp {
                //
                // Implements method type arguments inference
                //
-               bool InferInPhases (EmitContext ec, TypeInferenceContext tic, ParameterData methodParameters)
+               bool InferInPhases (EmitContext ec, TypeInferenceContext tic, AParametersCollection methodParameters)
                {
                        int params_arguments_start;
                        if (methodParameters.HasParams) {
@@ -2392,6 +2339,8 @@ namespace Mono.CSharp {
                        } else {
                                params_arguments_start = arg_count;
                        }
+
+                       Type [] ptypes = methodParameters.Types;
                        
                        //
                        // The first inference phase
@@ -2407,6 +2356,9 @@ namespace Mono.CSharp {
                                                method_parameter = methodParameters.Types [params_arguments_start];
                                        else
                                                method_parameter = TypeManager.GetElementType (methodParameters.Types [params_arguments_start]);
+
+                                       ptypes = (Type[]) ptypes.Clone ();
+                                       ptypes [i] = method_parameter;
                                }
 
                                //
@@ -2420,7 +2372,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               if (a.Expr.Type == TypeManager.null_type)
+                               if (a.Expr is NullLiteral)
                                        continue;
 
                                //
@@ -2434,16 +2386,16 @@ namespace Mono.CSharp {
                        // we don't need to call it in cycle
                        //
                        bool fixed_any = false;
-                       if (!tic.FixIndependentTypeArguments (methodParameters, ref fixed_any))
+                       if (!tic.FixIndependentTypeArguments (ptypes, ref fixed_any))
                                return false;
 
-                       return DoSecondPhase (ec, tic, methodParameters, !fixed_any);
+                       return DoSecondPhase (ec, tic, ptypes, !fixed_any);
                }
 
-               bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, ParameterData methodParameters, bool fixDependent)
+               bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, Type[] methodParameters, bool fixDependent)
                {
                        bool fixed_any = false;
-                       if (fixDependent && !tic.FixDependentTypes (methodParameters, ref fixed_any))
+                       if (fixDependent && !tic.FixDependentTypes (ref fixed_any))
                                return false;
 
                        // If no further unfixed type variables exist, type inference succeeds
@@ -2457,7 +2409,10 @@ namespace Mono.CSharp {
                        // contain unfixed type variables but the input types do not,
                        // an output type inference is made
                        for (int i = 0; i < arg_count; i++) {
-                               Type t_i = methodParameters.ParameterType (i);
+                               
+                               // Align params arguments
+                               Type t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i];
+                               
                                if (!TypeManager.IsDelegateType (t_i)) {
                                        if (TypeManager.DropGenericTypeArguments (t_i) != TypeManager.expression_type)
                                                continue;
@@ -2488,6 +2443,7 @@ namespace Mono.CSharp {
                readonly Type[] unfixed_types;
                readonly Type[] fixed_types;
                readonly ArrayList[] bounds;
+               bool failed;
                
                public TypeInferenceContext (Type[] typeArguments)
                {
@@ -2516,6 +2472,12 @@ namespace Mono.CSharp {
 
                void AddToBounds (Type t, int index)
                {
+                       //
+                       // Some types cannot be used as type arguments
+                       //
+                       if (t == TypeManager.void_type || t.IsPointer)
+                               return;
+
                        ArrayList a = bounds [index];
                        if (a == null) {
                                a = new ArrayList ();
@@ -2528,13 +2490,13 @@ namespace Mono.CSharp {
                        //
                        // SPEC: does not cover type inference using constraints
                        //
-                       if (TypeManager.IsGenericParameter (t)) {
-                               GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
-                               if (constraints != null) {
-                                       //if (constraints.EffectiveBaseClass != null)
-                                       //      t = constraints.EffectiveBaseClass;
-                               }
-                       }
+                       //if (TypeManager.IsGenericParameter (t)) {
+                       //    GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
+                       //    if (constraints != null) {
+                       //        //if (constraints.EffectiveBaseClass != null)
+                       //        //    t = constraints.EffectiveBaseClass;
+                       //    }
+                       //}
                        a.Add (t);
                }
                
@@ -2610,7 +2572,7 @@ namespace Mono.CSharp {
                // a, There is at least one type variable Xj that depends on Xi
                // b, Xi has a non-empty set of bounds
                // 
-               public bool FixDependentTypes (ParameterData methodParameters, ref bool fixed_any)
+               public bool FixDependentTypes (ref bool fixed_any)
                {
                        for (int i = 0; i < unfixed_types.Length; ++i) {
                                if (unfixed_types[i] == null)
@@ -2631,11 +2593,11 @@ namespace Mono.CSharp {
                //
                // All unfixed type variables Xi which depend on no Xj are fixed
                //
-               public bool FixIndependentTypeArguments (ParameterData methodParameters, ref bool fixed_any)
+               public bool FixIndependentTypeArguments (Type[] methodParameters, ref bool fixed_any)
                {
                        ArrayList types_to_fix = new ArrayList (unfixed_types);
-                       for (int i = 0; i < methodParameters.Types.Length; ++i) {
-                               Type t = methodParameters.Types [i];
+                       for (int i = 0; i < methodParameters.Length; ++i) {
+                               Type t = methodParameters[i];
                                if (t.IsGenericParameter)
                                        continue;
 
@@ -2685,6 +2647,9 @@ namespace Mono.CSharp {
                        if (unfixed_types[i] == null)
                                throw new InternalErrorException ("Type argument has been already fixed");
 
+                       if (failed)
+                               return false;
+
                        ArrayList candidates = (ArrayList)bounds [i];
                        if (candidates == null)
                                return false;
@@ -2737,8 +2702,15 @@ namespace Mono.CSharp {
                //
                public Type InflateGenericArgument (Type parameter)
                {
-                       if (parameter.IsGenericParameter)
+                       if (parameter.IsGenericParameter) {
+                               //
+                               // Inflate method generic argument (MVAR) only
+                               //
+                               if (parameter.DeclaringMethod == null)
+                                       return parameter;
+
                                return fixed_types [parameter.GenericParameterPosition];
+                       }
 
                        if (parameter.IsGenericType) {
                                Type [] parameter_targs = parameter.GetGenericArguments ();
@@ -2776,7 +2748,7 @@ namespace Mono.CSharp {
                        }
 
                        // All generic input arguments have to be fixed
-                       ParameterData d_parameters = TypeManager.GetParameterData (invoke);
+                       AParametersCollection d_parameters = TypeManager.GetParameterData (invoke);
                        return AllTypesAreFixed (d_parameters.Types);
                }
                
@@ -2804,10 +2776,6 @@ namespace Mono.CSharp {
                //
                public int LowerBoundInference (Type u, Type v)
                {
-                       // Remove ref, out modifiers
-                       if (v.IsByRef)
-                               v = v.GetElementType ();
-                       
                        // If V is one of the unfixed type arguments
                        int pos = IsUnfixed (v);
                        if (pos != -1) {
@@ -2871,7 +2839,8 @@ namespace Mono.CSharp {
                                u_candidates.AddRange (TypeManager.GetInterfaces (u));
 
                                Type open_v = v.GetGenericTypeDefinition ();
-                               int score = 0;
+                               Type [] unique_candidate_targs = null;
+                               Type [] ga_v = v.GetGenericArguments ();                        
                                foreach (Type u_candidate in u_candidates) {
                                        if (!u_candidate.IsGenericType || u_candidate.IsGenericTypeDefinition)
                                                continue;
@@ -2879,17 +2848,35 @@ namespace Mono.CSharp {
                                        if (TypeManager.DropGenericTypeArguments (u_candidate) != open_v)
                                                continue;
 
-                                       Type [] ga_u = u_candidate.GetGenericArguments ();
-                                       Type [] ga_v = v.GetGenericArguments ();
-                                       bool all_exact = true;
-                                       for (int i = 0; i < ga_u.Length; ++i)
-                                               if (ExactInference (ga_u [i], ga_v [i]) == 0)
-                                                       all_exact = false;
+                                       //
+                                       // The unique set of types U1..Uk means that if we have an interface C<T>,
+                                       // class U: C<int>, C<long> then no type inference is made when inferring
+                                       // from U to C<T> because T could be int or long
+                                       //
+                                       if (unique_candidate_targs != null) {
+                                               Type[] second_unique_candidate_targs = u_candidate.GetGenericArguments ();
+                                               if (TypeManager.IsEqual (unique_candidate_targs, second_unique_candidate_targs)) {
+                                                       unique_candidate_targs = second_unique_candidate_targs;
+                                                       continue;
+                                               }
+                                               
+                                               //
+                                               // This should always cause type inference failure
+                                               //
+                                               failed = true;
+                                               return 1;
+                                       }
 
-                                       if (all_exact && score == 0)
-                                               ++score;
+                                       unique_candidate_targs = u_candidate.GetGenericArguments ();
+                               }
+
+                               if (unique_candidate_targs != null) {
+                                       int score = 0;
+                                       for (int i = 0; i < unique_candidate_targs.Length; ++i)
+                                               if (ExactInference (unique_candidate_targs [i], ga_v [i]) == 0)
+                                                       ++score;
+                                       return score;
                                }
-                               return score;
                        }
 
                        return 0;
@@ -2907,7 +2894,7 @@ namespace Mono.CSharp {
                                MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
 
                                if (rt == null) {
-                                       ParameterData pd = TypeManager.GetParameterData (invoke);
+                                       AParametersCollection pd = TypeManager.GetParameterData (invoke);
                                        return ame.Parameters.Count == pd.Count ? 1 : 0;
                                }
 
@@ -2920,16 +2907,37 @@ namespace Mono.CSharp {
                                return LowerBoundInference (rt, rtype) + 1;
                        }
 
+                       //
+                       // if E is a method group and T is a delegate type or expression tree type
+                       // return type Tb with parameter types T1..Tk and return type Tb, and overload
+                       // resolution of E with the types T1..Tk yields a single method with return type U,
+                       // then a lower-bound inference is made from U for Tb.
+                       //
                        if (e is MethodGroupExpr) {
+                               // TODO: Or expression tree
                                if (!TypeManager.IsDelegateType (t))
                                        return 0;
 
                                MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
                                Type rtype = invoke.ReturnType;
+#if MS_COMPATIBLE
+                               // Blablabla, because reflection does not work with dynamic types
+                               Type [] g_args = t.GetGenericArguments ();
+                               rtype = g_args [rtype.GenericParameterPosition];
+#endif
+
                                if (!TypeManager.IsGenericType (rtype))
                                        return 0;
-                               
+
+                               MethodGroupExpr mg = (MethodGroupExpr) e;
+                               ArrayList args = DelegateCreation.CreateDelegateMethodArguments (invoke, e.Location);
+                               mg = mg.OverloadResolve (ec, ref args, true, e.Location);
+                               if (mg == null)
+                                       return 0;
+
+                               // TODO: What should happen when return type is of generic type ?
                                throw new NotImplementedException ();
+//                             return LowerBoundInference (null, rtype) + 1;
                        }
 
                        //