* MonoTouch/MonoPInvokeCallbackAttribute.cs: Added.
[mono.git] / mcs / mcs / generic.cs
index fa210289ecf3efe896b27a4421e47b52f5cfb926..999d6d9bbaaa0ac7a075fcf00b3ad1451aec7fdc 100644 (file)
@@ -103,7 +103,7 @@ namespace Mono.CSharp {
                                        return false;
 
                                if (ClassConstraint != null) {
-                                       if (!ClassConstraint.IsValueType)
+                                       if (!TypeManager.IsValueType (ClassConstraint))
                                                return false;
 
                                        if (ClassConstraint != TypeManager.value_type)
@@ -124,6 +124,79 @@ namespace Mono.CSharp {
                }
        }
 
+       public class ReflectionConstraints : GenericConstraints
+       {
+               GenericParameterAttributes attrs;
+               Type base_type;
+               Type class_constraint;
+               Type[] iface_constraints;
+               string name;
+
+               public static GenericConstraints GetConstraints (Type t)
+               {
+                       Type[] constraints = t.GetGenericParameterConstraints ();
+                       GenericParameterAttributes attrs = t.GenericParameterAttributes;
+                       if (constraints.Length == 0 && attrs == GenericParameterAttributes.None)
+                               return null;
+                       return new ReflectionConstraints (t.Name, constraints, attrs);
+               }
+
+               private ReflectionConstraints (string name, Type[] constraints, GenericParameterAttributes attrs)
+               {
+                       this.name = name;
+                       this.attrs = attrs;
+
+                       if ((constraints.Length > 0) && !constraints[0].IsInterface) {
+                               class_constraint = constraints[0];
+                               iface_constraints = new Type[constraints.Length - 1];
+                               Array.Copy (constraints, 1, iface_constraints, 0, constraints.Length - 1);
+                       } else
+                               iface_constraints = constraints;
+
+                       if (HasValueTypeConstraint)
+                               base_type = TypeManager.value_type;
+                       else if (class_constraint != null)
+                               base_type = class_constraint;
+                       else
+                               base_type = TypeManager.object_type;
+               }
+
+               public override string TypeParameter
+               {
+                       get { return name; }
+               }
+
+               public override GenericParameterAttributes Attributes
+               {
+                       get { return attrs; }
+               }
+
+               public override Type ClassConstraint
+               {
+                       get { return class_constraint; }
+               }
+
+               public override Type EffectiveBaseClass
+               {
+                       get { return base_type; }
+               }
+
+               public override Type[] InterfaceConstraints
+               {
+                       get { return iface_constraints; }
+               }
+       }
+
+       public enum Variance
+       {
+               //
+               // Don't add or modify internal values, they are used as -/+ calculation signs
+               //
+               None                    = 0,
+               Covariant               = 1,
+               Contravariant   = -1
+       }
+
        public enum SpecialConstraint
        {
                Constructor,
@@ -177,11 +250,14 @@ namespace Mono.CSharp {
                ///   Resolve the constraints - but only resolve things into Expression's, not
                ///   into actual types.
                /// </summary>
-               public bool Resolve (IResolveContext ec)
+               public bool Resolve (MemberCore ec, TypeParameter tp, Report Report)
                {
                        if (resolved)
                                return true;
 
+                       if (ec == null)
+                               return false;
+
                        iface_constraints = new ArrayList (2);  // TODO: Too expensive allocation
                        type_param_constraints = new ArrayList ();
 
@@ -226,33 +302,29 @@ namespace Mono.CSharp {
                                        if (errors != Report.Errors)
                                                return false;
 
-                                       NamespaceEntry.Error_NamespaceNotFound (loc, ((Expression)obj).GetSignatureForError ());
+                                       NamespaceEntry.Error_NamespaceNotFound (loc, ((Expression)obj).GetSignatureForError (), Report);
                                        return false;
                                }
 
                                TypeExpr expr;
-                               ConstructedType cexpr = fn as ConstructedType;
+                               GenericTypeExpr cexpr = fn as GenericTypeExpr;
                                if (cexpr != null) {
-                                       if (!cexpr.ResolveConstructedType (ec))
-                                               return false;
-
-                                       expr = cexpr;
+                                       expr = cexpr.ResolveAsBaseTerminal (ec, false);
                                } else
                                        expr = ((Expression) obj).ResolveAsTypeTerminal (ec, false);
 
                                if ((expr == null) || (expr.Type == null))
                                        return false;
 
-                               if (!ec.GenericDeclContainer.IsAccessibleAs (fn.Type)) {
+                               if (!ec.IsAccessibleAs (fn.Type)) {
                                        Report.SymbolRelatedToPreviousError (fn.Type);
                                        Report.Error (703, loc,
                                                "Inconsistent accessibility: constraint type `{0}' is less accessible than `{1}'",
-                                               fn.GetSignatureForError (), ec.GenericDeclContainer.GetSignatureForError ());
+                                               fn.GetSignatureForError (), ec.GetSignatureForError ());
                                        return false;
                                }
 
-                               TypeParameterExpr texpr = expr as TypeParameterExpr;
-                               if (texpr != null)
+                               if (TypeManager.IsGenericParameter (expr.Type))
                                        type_param_constraints.Add (expr);
                                else if (expr.IsInterface)
                                        iface_constraints.Add (expr);
@@ -269,6 +341,15 @@ namespace Mono.CSharp {
                                } else
                                        class_constraint = expr;
 
+
+                               //
+                               // Checks whether each generic method parameter constraint type
+                               // is valid with respect to T
+                               //
+                               if (tp != null && tp.Type.DeclaringMethod != null) {
+                                       TypeManager.CheckTypeVariance (expr.Type, Variance.Contravariant, ec as MemberCore);
+                               }
+
                                num_constraints++;
                        }
 
@@ -288,7 +369,7 @@ namespace Mono.CSharp {
                                list.Add (iface_constraint.Type);
                        }
 
-                       foreach (TypeParameterExpr expr in type_param_constraints) {
+                       foreach (TypeExpr expr in type_param_constraints) {
                                foreach (Type type in list) {
                                        if (!type.Equals (expr.Type))
                                                continue;
@@ -335,6 +416,11 @@ namespace Mono.CSharp {
                                                      TypeManager.CSharpName (class_constraint_type));
                                        return false;
                                }
+
+                               if (TypeManager.IsDynamicType (class_constraint_type)) {
+                                       Report.Error (1967, loc, "A constraint cannot be the dynamic type");
+                                       return false;
+                               }
                        }
 
                        if (class_constraint_type != null)
@@ -351,11 +437,11 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               bool CheckTypeParameterConstraints (TypeParameter tparam, ref TypeExpr prevConstraint, ArrayList seen)
+               bool CheckTypeParameterConstraints (Type tparam, ref TypeExpr prevConstraint, ArrayList seen, Report Report)
                {
                        seen.Add (tparam);
 
-                       Constraints constraints = tparam.Constraints;
+                       Constraints constraints = TypeManager.LookupTypeParameter (tparam).Constraints;
                        if (constraints == null)
                                return true;
 
@@ -393,15 +479,15 @@ namespace Mono.CSharp {
                        if (constraints.type_param_constraints == null)
                                return true;
 
-                       foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
-                               if (seen.Contains (expr.TypeParameter)) {
+                       foreach (TypeExpr expr in constraints.type_param_constraints) {
+                               if (seen.Contains (expr.Type)) {
                                        Report.Error (454, loc, "Circular constraint " +
                                                      "dependency involving `{0}' and `{1}'",
                                                      tparam.Name, expr.GetSignatureForError ());
                                        return false;
                                }
 
-                               if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prevConstraint, seen))
+                               if (!CheckTypeParameterConstraints (expr.Type, ref prevConstraint, seen, Report))
                                        return false;
                        }
 
@@ -411,7 +497,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Resolve the constraints into actual types.
                /// </summary>
-               public bool ResolveTypes (IResolveContext ec)
+               public bool ResolveTypes (IMemberContext ec, Report r)
                {
                        if (resolved_types)
                                return true;
@@ -419,7 +505,7 @@ namespace Mono.CSharp {
                        resolved_types = true;
 
                        foreach (object obj in constraints) {
-                               ConstructedType cexpr = obj as ConstructedType;
+                               GenericTypeExpr cexpr = obj as GenericTypeExpr;
                                if (cexpr == null)
                                        continue;
 
@@ -430,8 +516,8 @@ namespace Mono.CSharp {
                        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))
+                               foreach (TypeExpr expr in type_param_constraints) {
+                                       if (!CheckTypeParameterConstraints (expr.Type, ref prev_constraint, seen, r))
                                                return false;
                                        seen.Clear ();
                                }
@@ -528,7 +614,7 @@ namespace Mono.CSharp {
                                        iface = iface.GetGenericTypeDefinition ();
                                
                                bool ok = false;
-                               for (int ii = 0; i < InterfaceConstraints.Length; ++ii) {
+                               for (int ii = 0; ii < InterfaceConstraints.Length; ii++) {
                                        Type check = InterfaceConstraints [ii];
                                        if (check.IsGenericType)
                                                check = check.GetGenericTypeDefinition ();
@@ -546,21 +632,21 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public void VerifyClsCompliance ()
+               public void VerifyClsCompliance (Report r)
                {
                        if (class_constraint_type != null && !AttributeTester.IsClsCompliant (class_constraint_type))
-                               Warning_ConstrainIsNotClsCompliant (class_constraint_type, class_constraint.Location);
+                               Warning_ConstrainIsNotClsCompliant (class_constraint_type, class_constraint.Location, r);
 
                        if (iface_constraint_types != null) {
                                for (int i = 0; i < iface_constraint_types.Length; ++i) {
                                        if (!AttributeTester.IsClsCompliant (iface_constraint_types [i]))
                                                Warning_ConstrainIsNotClsCompliant (iface_constraint_types [i],
-                                                       ((TypeExpr)iface_constraints [i]).Location);
+                                                       ((TypeExpr)iface_constraints [i]).Location, r);
                                }
                        }
                }
 
-               void Warning_ConstrainIsNotClsCompliant (Type t, Location loc)
+               void Warning_ConstrainIsNotClsCompliant (Type t, Location loc, Report Report)
                {
                        Report.SymbolRelatedToPreviousError (t);
                        Report.Warning (3024, 1, loc, "Constraint type `{0}' is not CLS-compliant",
@@ -575,20 +661,20 @@ namespace Mono.CSharp {
        {
                static readonly string[] attribute_target = new string [] { "type parameter" };
                
-               string name;
                DeclSpace decl;
                GenericConstraints gc;
                Constraints constraints;
                GenericTypeParameterBuilder type;
                MemberCache member_cache;
+               Variance variance;
 
                public TypeParameter (DeclSpace parent, DeclSpace decl, string name,
-                                     Constraints constraints, Attributes attrs, Location loc)
+                                     Constraints constraints, Attributes attrs, Variance variance, Location loc)
                        : base (parent, new MemberName (name, loc), attrs)
                {
-                       this.name = name;
                        this.decl = decl;
                        this.constraints = constraints;
+                       this.variance = variance;
                }
 
                public GenericConstraints GenericConstraints {
@@ -603,6 +689,10 @@ namespace Mono.CSharp {
                        get { return decl; }
                }
 
+               public Variance Variance {
+                       get { return variance; }
+               }
+
                public Type Type {
                        get { return type; }
                }
@@ -625,6 +715,25 @@ namespace Mono.CSharp {
                        TypeManager.AddTypeParameter (type, this);
                }
 
+               public void ErrorInvalidVariance (IMemberContext mc, Variance expected)
+               {
+// TODO:       Report.SymbolRelatedToPreviousError (mc);
+                       string input_variance = Variance == Variance.Contravariant ? "contravariant" : "covariant";
+                       string gtype_variance;
+                       switch (expected) {
+                       case Variance.Contravariant: gtype_variance = "contravariantly"; break;
+                       case Variance.Covariant: gtype_variance = "covariantly"; break;
+                       default: gtype_variance = "invariantly"; break;
+                       }
+
+                       Delegate d = mc as Delegate;
+                       string parameters = d != null ? d.Parameters.GetSignatureForError () : "";
+
+                       Report.Error (1961, Location,
+                               "The {2} type parameter `{0}' must be {3} valid on `{1}{4}'",
+                                       GetSignatureForError (), mc.GetSignatureForError (), input_variance, gtype_variance, parameters);
+               }
+
                /// <summary>
                ///   This is the second method which is called during the resolving
                ///   process - in case of class type parameters, we're called from
@@ -641,7 +750,7 @@ namespace Mono.CSharp {
                public bool Resolve (DeclSpace ds)
                {
                        if (constraints != null) {
-                               if (!constraints.Resolve (ds)) {
+                               if (!constraints.Resolve (ds, this, Report)) {
                                        constraints = null;
                                        return false;
                                }
@@ -660,10 +769,10 @@ namespace Mono.CSharp {
                ///   Note that we may have circular dependencies on type parameters - this
                ///   is why Resolve() and ResolveType() are separate.
                /// </summary>
-               public bool ResolveType (IResolveContext ec)
+               public bool ResolveType (IMemberContext ec)
                {
                        if (constraints != null) {
-                               if (!constraints.ResolveTypes (ec)) {
+                               if (!constraints.ResolveTypes (ec, Report)) {
                                        constraints = null;
                                        return false;
                                }
@@ -677,7 +786,7 @@ namespace Mono.CSharp {
                ///   process.  We're called after everything is fully resolved and actually
                ///   register the constraints with SRE and the TypeManager.
                /// </summary>
-               public bool DefineType (IResolveContext ec)
+               public bool DefineType (IMemberContext ec)
                {
                        return DefineType (ec, null, null, false);
                }
@@ -690,7 +799,7 @@ namespace Mono.CSharp {
                ///   The `builder', `implementing' and `is_override' arguments are only
                ///   applicable to method type parameters.
                /// </summary>
-               public bool DefineType (IResolveContext ec, MethodBuilder builder,
+               public bool DefineType (IMemberContext ec, MethodBuilder builder,
                                        MethodInfo implementing, bool is_override)
                {
                        if (!ResolveType (ec))
@@ -751,17 +860,38 @@ namespace Mono.CSharp {
                                gc = (GenericConstraints) constraints;
                        }
 
-                       if (gc == null)
-                               return true;
+                       SetConstraints (type);
+                       return true;
+               }
 
-                       if (gc.HasClassConstraint || gc.HasValueTypeConstraint)
-                               type.SetBaseTypeConstraint (gc.EffectiveBaseClass);
+               public static TypeParameter FindTypeParameter (TypeParameter[] tparams, string name)
+               {
+                       foreach (var tp in tparams) {
+                               if (tp.Name == name)
+                                       return tp;
+                       }
 
-                       type.SetInterfaceConstraints (gc.InterfaceConstraints);
-                       type.SetGenericParameterAttributes (gc.Attributes);
-                       TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
+                       return null;
+               }
 
-                       return true;
+               public void SetConstraints (GenericTypeParameterBuilder type)
+               {
+                       GenericParameterAttributes attr = GenericParameterAttributes.None;
+                       if (variance == Variance.Contravariant)
+                               attr |= GenericParameterAttributes.Contravariant;
+                       else if (variance == Variance.Covariant)
+                               attr |= GenericParameterAttributes.Covariant;
+
+                       if (gc != null) {
+                               if (gc.HasClassConstraint || gc.HasValueTypeConstraint)
+                                       type.SetBaseTypeConstraint (gc.EffectiveBaseClass);
+
+                               attr |= gc.Attributes;
+                               type.SetInterfaceConstraints (gc.InterfaceConstraints);
+                               TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
+                       }
+                       
+                       type.SetGenericParameterAttributes (attr);
                }
 
                /// <summary>
@@ -772,7 +902,7 @@ namespace Mono.CSharp {
                ///   check that they're the same.
                ///   con
                /// </summary>
-               public bool UpdateConstraints (IResolveContext ec, Constraints new_constraints)
+               public bool UpdateConstraints (MemberCore ec, Constraints new_constraints)
                {
                        if (type == null)
                                throw new InvalidOperationException ();
@@ -780,9 +910,9 @@ namespace Mono.CSharp {
                        if (new_constraints == null)
                                return true;
 
-                       if (!new_constraints.Resolve (ec))
+                       if (!new_constraints.Resolve (ec, this, Report))
                                return false;
-                       if (!new_constraints.ResolveTypes (ec))
+                       if (!new_constraints.ResolveTypes (ec, Report))
                                return false;
 
                        if (constraints != null) 
@@ -816,8 +946,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public override void ApplyAttributeBuilder (Attribute a,
-                                                           CustomAttributeBuilder cb)
+               public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
                {
                        type.SetCustomAttribute (cb);
                }
@@ -915,26 +1044,6 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               public override string ToString ()
-               {
-                       return "TypeParameter[" + name + "]";
-               }
-
-               public static string GetSignatureForError (TypeParameter[] tp)
-               {
-                       if (tp == null || tp.Length == 0)
-                               return "";
-
-                       StringBuilder sb = new StringBuilder ("<");
-                       for (int i = 0; i < tp.Length; ++i) {
-                               if (i > 0)
-                                       sb.Append (",");
-                               sb.Append (tp[i].GetSignatureForError ());
-                       }
-                       sb.Append ('>');
-                       return sb.ToString ();
-               }
-
                public void InflateConstraints (Type declaring)
                {
                        if (constraints != null)
@@ -1038,29 +1147,21 @@ namespace Mono.CSharp {
        ///   A TypeExpr which already resolved to a type parameter.
        /// </summary>
        public class TypeParameterExpr : TypeExpr {
-               TypeParameter type_parameter;
-
-               public TypeParameter TypeParameter {
-                       get {
-                               return type_parameter;
-                       }
-               }
                
                public TypeParameterExpr (TypeParameter type_parameter, Location loc)
                {
-                       this.type_parameter = type_parameter;
+                       this.type = type_parameter.Type;
+                       this.eclass = ExprClass.TypeParameter;
                        this.loc = loc;
                }
 
-               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
+               protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
                {
                        throw new NotSupportedException ();
                }
 
-               public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
+               public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
                {
-                       type = type_parameter.Type;
-                       eclass = ExprClass.TypeParameter;
                        return this;
                }
 
@@ -1068,42 +1169,31 @@ namespace Mono.CSharp {
                        get { return false; }
                }
 
-               public override bool CheckAccessLevel (DeclSpace ds)
+               public override bool CheckAccessLevel (IMemberContext ds)
                {
                        return true;
                }
        }
 
-       /// <summary>
-       ///   Tracks the type arguments when instantiating a generic type.  We're used in
-       ///   ConstructedType.
-       /// </summary>
+       //
+       // Tracks the type arguments when instantiating a generic type. It's used
+       // by both type arguments and type parameters
+       //
        public class TypeArguments {
-               public readonly Location Location;
                ArrayList args;
                Type[] atypes;
-               int dimension;
-               bool has_type_args;
                
-               public TypeArguments (Location loc)
+               public TypeArguments ()
                {
                        args = new ArrayList ();
-                       this.Location = loc;
                }
 
-               public TypeArguments (Location loc, params Expression[] types)
+               public TypeArguments (params FullNamedExpression[] types)
                {
-                       this.Location = loc;
                        this.args = new ArrayList (types);
                }
-               
-               public TypeArguments (int dimension, Location loc)
-               {
-                       this.dimension = dimension;
-                       this.Location = loc;
-               }
 
-               public void Add (Expression type)
+               public void Add (FullNamedExpression type)
                {
                        args.Add (type);
                }
@@ -1113,33 +1203,10 @@ namespace Mono.CSharp {
                        args.AddRange (new_args.args);
                }
 
-               /// <summary>
-               ///   We're used during the parsing process: the parser can't distinguish
-               ///   between type parameters and type arguments.  Because of that, the
-               ///   parser creates a `MemberName' with `TypeArguments' for both cases and
-               ///   in case of a generic type definition, we call GetDeclarations().
-               /// </summary>
+               // TODO: Should be deleted
                public TypeParameterName[] GetDeclarations ()
                {
-                       TypeParameterName[] ret = new TypeParameterName [args.Count];
-                       for (int i = 0; i < args.Count; i++) {
-                               TypeParameterName name = args [i] as TypeParameterName;
-                               if (name != null) {
-                                       ret [i] = name;
-                                       continue;
-                               }
-                               SimpleName sn = args [i] as SimpleName;
-                               if (sn != null && !sn.HasTypeArguments) {
-                                       ret [i] = new TypeParameterName (sn.Name, null, sn.Location);
-                                       continue;
-                               }
-
-                               Expression expr = (Expression) args [i];
-                               // TODO: Wrong location
-                               Report.Error (81, Location, "Type parameter declaration must be an identifier not a type");
-                               ret [i] = new TypeParameterName (expr.GetSignatureForError (), null, expr.Location);
-                       }
-                       return ret;
+                       return (TypeParameterName[]) args.ToArray (typeof (TypeParameterName));
                }
 
                /// <summary>
@@ -1152,44 +1219,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool HasTypeArguments {
-                       get {
-                               return has_type_args;
-                       }
-               }
-
                public int Count {
                        get {
-                               if (dimension > 0)
-                                       return dimension;
-                               else
-                                       return args.Count;
-                       }
-               }
-
-               public bool IsUnbound {
-                       get {
-                               return dimension > 0;
+                               return args.Count;
                        }
                }
 
-               public override string ToString ()
-               {
-                       StringBuilder s = new StringBuilder ();
-
-                       int count = Count;
-                       for (int i = 0; i < count; i++){
-                               //
-                               // FIXME: Use TypeManager.CSharpname once we have the type
-                               //
-                               if (args != null)
-                                       s.Append (args [i].ToString ());
-                               if (i+1 < count)
-                                       s.Append (",");
-                       }
-                       return s.ToString ();
-               }
-
                public string GetSignatureForError()
                {
                        StringBuilder sb = new StringBuilder();
@@ -1206,51 +1241,48 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Resolve the type arguments.
                /// </summary>
-               public bool Resolve (IResolveContext ec)
+               public bool Resolve (IMemberContext ec)
                {
+                       if (atypes != null)
+                               return atypes.Length != 0;
+
                        int count = args.Count;
                        bool ok = true;
 
                        atypes = new Type [count];
 
                        for (int i = 0; i < count; i++){
-                               TypeExpr te = ((Expression) args [i]).ResolveAsTypeTerminal (ec, false);
+                               TypeExpr te = ((FullNamedExpression) args[i]).ResolveAsTypeTerminal (ec, false);
                                if (te == null) {
                                        ok = false;
                                        continue;
                                }
 
                                atypes[i] = te.Type;
-                               if (te.Type.IsGenericParameter) {
-                                       if (te is TypeParameterExpr)
-                                               has_type_args = true;
-                                       continue;
-                               }
 
                                if (te.Type.IsSealed && te.Type.IsAbstract) {
-                                       Report.Error (718, Location, "`{0}': static classes cannot be used as generic arguments",
+                                       ec.Compiler.Report.Error (718, te.Location, "`{0}': static classes cannot be used as generic arguments",
                                                te.GetSignatureForError ());
-                                       return false;
+                                       ok = false;
                                }
 
                                if (te.Type.IsPointer || TypeManager.IsSpecialType (te.Type)) {
-                                       Report.Error (306, Location,
+                                       ec.Compiler.Report.Error (306, te.Location,
                                                "The type `{0}' may not be used as a type argument",
-                                               TypeManager.CSharpName (te.Type));
-                                       return false;
-                               }
-
-                               if (te.Type == TypeManager.void_type) {
-                                       Expression.Error_VoidInvalidInTheContext (Location);
-                                       return false;
+                                               te.GetSignatureForError ());
+                                       ok = false;
                                }
                        }
+
+                       if (!ok)
+                               atypes = Type.EmptyTypes;
+
                        return ok;
                }
 
                public TypeArguments Clone ()
                {
-                       TypeArguments copy = new TypeArguments (Location);
+                       TypeArguments copy = new TypeArguments ();
                        foreach (Expression ta in args)
                                copy.args.Add (ta);
 
@@ -1261,11 +1293,18 @@ namespace Mono.CSharp {
        public class TypeParameterName : SimpleName
        {
                Attributes attributes;
+               Variance variance;
 
                public TypeParameterName (string name, Attributes attrs, Location loc)
+                       : this (name, attrs, Variance.None, loc)
+               {
+               }
+
+               public TypeParameterName (string name, Attributes attrs, Variance variance, Location loc)
                        : base (name, loc)
                {
                        attributes = attrs;
+                       this.variance = variance;
                }
 
                public Attributes OptAttributes {
@@ -1273,43 +1312,38 @@ namespace Mono.CSharp {
                                return attributes;
                        }
                }
+
+               public Variance Variance {
+                       get {
+                               return variance;
+                       }
+               }
        }
 
        /// <summary>
-       ///   An instantiation of a generic type.
+       ///   A reference expression to generic type
        /// </summary>  
-       public class ConstructedType : TypeExpr {
-               FullNamedExpression name;
+       class GenericTypeExpr : TypeExpr
+       {
                TypeArguments args;
-               Type[] gen_params, atypes;
-               Type gt;
-
-               /// <summary>
-               ///   Instantiate the generic type `fname' with the type arguments `args'.
-               /// </summary>          
-               public ConstructedType (FullNamedExpression fname, TypeArguments args, Location l)
-               {
-                       loc = l;
-                       this.name = fname;
-                       this.args = args;
+               Type[] gen_params;      // TODO: Waiting for constrains check cleanup
+               Type open_type;
 
-                       eclass = ExprClass.Type;
-               }
-
-               /// <summary>
-               ///   This is used to construct the `this' type inside a generic type definition.
-               /// </summary>
-               public ConstructedType (Type t, TypeParameter[] type_params, Location l)
+               //
+               // Should be carefully used only with defined generic containers. Type parameters
+               // can be used as type arguments in this case.
+               //
+               // TODO: This could be GenericTypeExpr specialization
+               //
+               public GenericTypeExpr (DeclSpace gType, Location l)
                {
-                       gt = t.GetGenericTypeDefinition ();
+                       open_type = gType.TypeBuilder.GetGenericTypeDefinition ();
 
-                       args = new TypeArguments (l);
-                       foreach (TypeParameter type_param in type_params)
+                       args = new TypeArguments ();
+                       foreach (TypeParameter type_param in gType.TypeParameters)
                                args.Add (new TypeParameterExpr (type_param, l));
 
                        this.loc = l;
-                       this.name = new TypeExpression (gt, l);
-                       eclass = ExprClass.Type;
                }
 
                /// <summary>
@@ -1317,11 +1351,12 @@ namespace Mono.CSharp {
                ///   Use this constructor if you already know the fully resolved
                ///   generic type.
                /// </summary>          
-               public ConstructedType (Type t, TypeArguments args, Location l)
-                       : this ((FullNamedExpression)null, args, l)
+               public GenericTypeExpr (Type t, TypeArguments args, Location l)
                {
-                       gt = t.GetGenericTypeDefinition ();
-                       this.name = new TypeExpression (gt, l);
+                       open_type = t.GetGenericTypeDefinition ();
+
+                       loc = l;
+                       this.args = args;
                }
 
                public TypeArguments TypeArguments {
@@ -1333,121 +1368,64 @@ namespace Mono.CSharp {
                        return TypeManager.CSharpName (type);
                }
 
-               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
-               {
-                       if (!ResolveConstructedType (ec))
-                               return null;
-
-                       return this;
-               }
-
-               /// <summary>
-               ///   Check the constraints; we're called from ResolveAsTypeTerminal()
-               ///   after fully resolving the constructed type.
-               /// </summary>
-               public bool CheckConstraints (IResolveContext ec)
-               {
-                       return ConstraintChecker.CheckConstraints (ec, gt, gen_params, atypes, loc);
-               }
-
-               /// <summary>
-               ///   Resolve the constructed type, but don't check the constraints.
-               /// </summary>
-               public bool ResolveConstructedType (IResolveContext ec)
+               protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
                {
-                       if (type != null)
-                               return true;
-                       // If we already know the fully resolved generic type.
-                       if (gt != null)
-                               return DoResolveType (ec);
+                       if (eclass != ExprClass.Invalid)
+                               return this;
 
-                       int num_args;
-                       Type t = name.Type;
-
-                       if (t == null) {
-                               Report.Error (246, loc, "Cannot find type `{0}'<...>", GetSignatureForError ());
-                               return false;
-                       }
-
-                       num_args = TypeManager.GetNumberOfTypeArguments (t);
-                       if (num_args == 0) {
-                               Report.Error (308, loc,
-                                             "The non-generic type `{0}' cannot " +
-                                             "be used with type arguments.",
-                                             TypeManager.CSharpName (t));
-                               return false;
-                       }
-
-                       gt = t.GetGenericTypeDefinition ();
-                       return DoResolveType (ec);
-               }
-
-               bool DoResolveType (IResolveContext ec)
-               {
-                       //
-                       // Resolve the arguments.
-                       //
-                       if (args.Resolve (ec) == false)
-                               return false;
+                       eclass = ExprClass.Type;
 
-                       gen_params = gt.GetGenericArguments ();
-                       atypes = args.Arguments;
+                       if (!args.Resolve (ec))
+                               return null;
 
+                       gen_params = open_type.GetGenericArguments ();
+                       Type[] atypes = args.Arguments;
+                       
                        if (atypes.Length != gen_params.Length) {
-                               Report.Error (305, loc,
-                                             "Using the generic type `{0}' " +
-                                             "requires {1} type arguments",
-                                             TypeManager.CSharpName (gt),
-                                             gen_params.Length.ToString ());
-                               return false;
+                               Namespace.Error_InvalidNumberOfTypeArguments (open_type, loc);
+                               return null;
                        }
 
                        //
-                       // Now bind the parameters.
+                       // Now bind the parameters
                        //
-                       type = gt.MakeGenericType (atypes);
-                       return true;
-               }
-
-               public Expression GetSimpleName (EmitContext ec)
-               {
+                       type = open_type.MakeGenericType (atypes);
                        return this;
                }
 
-               public override bool CheckAccessLevel (DeclSpace ds)
+               /// <summary>
+               ///   Check the constraints; we're called from ResolveAsTypeTerminal()
+               ///   after fully resolving the constructed type.
+               /// </summary>
+               public bool CheckConstraints (IMemberContext ec)
                {
-                       return ds.CheckAccessLevel (gt);
+                       return ConstraintChecker.CheckConstraints (ec, open_type, gen_params, args.Arguments, loc);
                }
-
-               public override bool AsAccessible (DeclSpace ds)
+       
+               public override bool CheckAccessLevel (IMemberContext mc)
                {
-                       foreach (Type t in atypes) {
-                               if (!ds.IsAccessibleAs (t))
-                                       return false;
-                       }
-
-                       return ds.IsAccessibleAs (gt);
+                       return mc.CurrentTypeDefinition.CheckAccessLevel (open_type);
                }
 
                public override bool IsClass {
-                       get { return gt.IsClass; }
+                       get { return open_type.IsClass; }
                }
 
                public override bool IsValueType {
-                       get { return gt.IsValueType; }
+                       get { return TypeManager.IsStruct (open_type); }
                }
 
                public override bool IsInterface {
-                       get { return gt.IsInterface; }
+                       get { return open_type.IsInterface; }
                }
 
                public override bool IsSealed {
-                       get { return gt.IsSealed; }
+                       get { return open_type.IsSealed; }
                }
 
                public override bool Equals (object obj)
                {
-                       ConstructedType cobj = obj as ConstructedType;
+                       GenericTypeExpr cobj = obj as GenericTypeExpr;
                        if (cobj == null)
                                return false;
 
@@ -1468,19 +1446,21 @@ namespace Mono.CSharp {
                protected readonly Type[] gen_params;
                protected readonly Type[] atypes;
                protected readonly Location loc;
+               protected Report Report;
 
-               protected ConstraintChecker (Type[] gen_params, Type[] atypes, Location loc)
+               protected ConstraintChecker (Type[] gen_params, Type[] atypes, Location loc, Report r)
                {
                        this.gen_params = gen_params;
                        this.atypes = atypes;
                        this.loc = loc;
+                       this.Report = r;
                }
 
                /// <summary>
                ///   Check the constraints; we're called from ResolveAsTypeTerminal()
                ///   after fully resolving the constructed type.
                /// </summary>
-               public bool CheckConstraints (IResolveContext ec)
+               public bool CheckConstraints (IMemberContext ec)
                {
                        for (int i = 0; i < gen_params.Length; i++) {
                                if (!CheckConstraints (ec, i))
@@ -1490,7 +1470,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               protected bool CheckConstraints (IResolveContext ec, int index)
+               protected bool CheckConstraints (IMemberContext ec, int index)
                {
                        Type atype = atypes [index];
                        Type ptype = gen_params [index];
@@ -1508,20 +1488,23 @@ namespace Mono.CSharp {
                        if (atype.IsGenericParameter) {
                                GenericConstraints agc = TypeManager.GetTypeParameterConstraints (atype);
                                if (agc != null) {
-                                       if (agc is Constraints)
-                                               ((Constraints) agc).Resolve (ec);
+                                       if (agc is Constraints) {
+                                               // FIXME: No constraints can be resolved here, we are in
+                                               // completely wrong/different context. This path is hit
+                                               // when resolving base type of unresolved generic type
+                                               // with constraints. We are waiting with CheckConsttraints
+                                               // after type-definition but not in this case
+                                               if (!((Constraints) agc).Resolve (null, null, Report))
+                                                       return true;
+                                       }
                                        is_class = agc.IsReferenceType;
                                        is_struct = agc.IsValueType;
                                } else {
                                        is_class = is_struct = false;
                                }
                        } else {
-#if MS_COMPATIBLE
-                               is_class = false;
-                               if (!atype.IsGenericType)
-#endif
-                               is_class = atype.IsClass || atype.IsInterface;
-                               is_struct = atype.IsValueType && !TypeManager.IsNullableType (atype);
+                               is_class = TypeManager.IsReferenceType (atype);
+                               is_struct = TypeManager.IsValueType (atype) && !TypeManager.IsNullableType (atype);
                        }
 
                        //
@@ -1572,7 +1555,7 @@ namespace Mono.CSharp {
                        if (!gc.HasConstructorConstraint)
                                return true;
 
-                       if (TypeManager.IsBuiltinType (atype) || atype.IsValueType)
+                       if (TypeManager.IsValueType (atype))
                                return true;
 
                        if (HasDefaultConstructor (atype))
@@ -1590,31 +1573,45 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               protected bool CheckConstraint (IResolveContext ec, Type ptype, Expression expr,
+               protected bool CheckConstraint (IMemberContext ec, Type ptype, Expression expr,
                                                Type ctype)
                {
+                       //
+                       // All this is needed because we don't have
+                       // real inflated type hierarchy
+                       //
                        if (TypeManager.HasGenericArguments (ctype)) {
                                Type[] types = TypeManager.GetTypeArguments (ctype);
 
-                               TypeArguments new_args = new TypeArguments (loc);
+                               TypeArguments new_args = new TypeArguments ();
 
                                for (int i = 0; i < types.Length; i++) {
-                                       Type t = types [i];
+                                       Type t = TypeManager.TypeToCoreType (types [i]);
 
                                        if (t.IsGenericParameter) {
                                                int pos = t.GenericParameterPosition;
-                                               t = atypes [pos];
+                                               if (t.DeclaringMethod == null && this is MethodConstraintChecker) {
+                                                       Type parent = ((MethodConstraintChecker) this).declaring_type;
+                                                       t = parent.GetGenericArguments ()[pos];
+                                               } else {
+                                                       t = atypes [pos];
+                                               }
                                        }
                                        new_args.Add (new TypeExpression (t, loc));
                                }
 
-                               TypeExpr ct = new ConstructedType (ctype, new_args, loc);
+                               TypeExpr ct = new GenericTypeExpr (ctype, new_args, loc);
                                if (ct.ResolveAsTypeStep (ec, false) == null)
                                        return false;
                                ctype = ct.Type;
                        } else if (ctype.IsGenericParameter) {
                                int pos = ctype.GenericParameterPosition;
-                               ctype = atypes [pos];
+                               if (ctype.DeclaringMethod == null) {
+                                       // FIXME: Implement
+                                       return true;
+                               } else {                                
+                                       ctype = atypes [pos];
+                               }
                        }
 
                        if (Convert.ImplicitStandardConversionExists (expr, ctype))
@@ -1694,21 +1691,21 @@ namespace Mono.CSharp {
                protected abstract string GetSignatureForError ();
                protected abstract void Report_SymbolRelatedToPreviousError ();
 
-               public static bool CheckConstraints (EmitContext ec, MethodBase definition,
+               public static bool CheckConstraints (IMemberContext ec, MethodBase definition,
                                                     MethodBase instantiated, Location loc)
                {
                        MethodConstraintChecker checker = new MethodConstraintChecker (
-                               definition, definition.GetGenericArguments (),
-                               instantiated.GetGenericArguments (), loc);
+                               definition, instantiated.DeclaringType, definition.GetGenericArguments (),
+                               instantiated.GetGenericArguments (), loc, ec.Compiler.Report);
 
                        return checker.CheckConstraints (ec);
                }
 
-               public static bool CheckConstraints (IResolveContext ec, Type gt, Type[] gen_params,
+               public static bool CheckConstraints (IMemberContext ec, Type gt, Type[] gen_params,
                                                     Type[] atypes, Location loc)
                {
                        TypeConstraintChecker checker = new TypeConstraintChecker (
-                               gt, gen_params, atypes, loc);
+                               gt, gen_params, atypes, loc, ec.Compiler.Report);
 
                        return checker.CheckConstraints (ec);
                }
@@ -1716,11 +1713,13 @@ namespace Mono.CSharp {
                protected class MethodConstraintChecker : ConstraintChecker
                {
                        MethodBase definition;
+                       public Type declaring_type;
 
-                       public MethodConstraintChecker (MethodBase definition, Type[] gen_params,
-                                                       Type[] atypes, Location loc)
-                               : base (gen_params, atypes, loc)
+                       public MethodConstraintChecker (MethodBase definition, Type declaringType, Type[] gen_params,
+                                                       Type[] atypes, Location loc, Report r)
+                               : base (gen_params, atypes, loc, r)
                        {
+                               this.declaring_type = declaringType;
                                this.definition = definition;
                        }
 
@@ -1740,8 +1739,8 @@ namespace Mono.CSharp {
                        Type gt;
 
                        public TypeConstraintChecker (Type gt, Type[] gen_params, Type[] atypes,
-                                                     Location loc)
-                               : base (gen_params, atypes, loc)
+                                                     Location loc, Report r)
+                               : base (gen_params, atypes, loc, r)
                        {
                                this.gt = gt;
                        }
@@ -1764,16 +1763,28 @@ namespace Mono.CSharp {
        public class GenericMethod : DeclSpace
        {
                FullNamedExpression return_type;
-               Parameters parameters;
+               ParametersCompiled parameters;
 
                public GenericMethod (NamespaceEntry ns, DeclSpace parent, MemberName name,
-                                     FullNamedExpression return_type, Parameters parameters)
+                                     FullNamedExpression return_type, ParametersCompiled parameters)
                        : base (ns, parent, name, null)
                {
                        this.return_type = return_type;
                        this.parameters = parameters;
                }
 
+               public override TypeContainer CurrentTypeDefinition {
+                       get {
+                               return Parent.CurrentTypeDefinition;
+                       }
+               }
+
+               public override TypeParameter[] CurrentTypeParameters {
+                       get {
+                               return base.type_params;
+                       }
+               }
+
                public override TypeBuilder DefineType ()
                {
                        throw new Exception ();
@@ -1792,22 +1803,26 @@ namespace Mono.CSharp {
                ///   Define and resolve the type parameters.
                ///   We're called from Method.Define().
                /// </summary>
-               public bool Define (MethodBuilder mb)
+               public bool Define (MethodOrOperator m)
                {
                        TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
                        string[] snames = new string [names.Length];
                        for (int i = 0; i < names.Length; i++) {
                                string type_argument_name = names[i].Name;
-                               Parameter p = parameters.GetParameterByName (type_argument_name);
-                               if (p != null) {
-                                       Error_ParameterNameCollision (p.Location, type_argument_name, "method parameter");
-                                       return false;
+                               int idx = parameters.GetParameterIndexByName (type_argument_name);
+                               if (idx >= 0) {
+                                       Block b = m.Block;
+                                       if (b == null)
+                                               b = new Block (null);
+
+                                       b.Error_AlreadyDeclaredTypeParameter (Report, parameters [i].Location,
+                                               type_argument_name, "method parameter");
                                }
                                
                                snames[i] = type_argument_name;
                        }
 
-                       GenericTypeParameterBuilder[] gen_params = mb.DefineGenericParameters (snames);
+                       GenericTypeParameterBuilder[] gen_params = m.MethodBuilder.DefineGenericParameters (snames);
                        for (int i = 0; i < TypeParameters.Length; i++)
                                TypeParameters [i].Define (gen_params [i]);
 
@@ -1822,16 +1837,10 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               internal static void Error_ParameterNameCollision (Location loc, string name, string collisionWith)
-               {
-                       Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
-                               name, collisionWith);
-               }
-
                /// <summary>
                ///   We're called from MethodData.Define() after creating the MethodBuilder.
                /// </summary>
-               public bool DefineType (EmitContext ec, MethodBuilder mb,
+               public bool DefineType (IMemberContext ec, MethodBuilder mb,
                                        MethodInfo implementing, bool is_override)
                {
                        for (int i = 0; i < TypeParameters.Length; i++)
@@ -1860,7 +1869,12 @@ namespace Mono.CSharp {
                                                        MemberFilter filter, object criteria)
                {
                        throw new Exception ();
-               }               
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return base.GetSignatureForError () + parameters.GetSignatureForError ();
+               }
 
                public override MemberCache MemberCache {
                        get {
@@ -1884,7 +1898,7 @@ namespace Mono.CSharp {
                                if (tp.Constraints == null)
                                        continue;
 
-                               tp.Constraints.VerifyClsCompliance ();
+                               tp.Constraints.VerifyClsCompliance (Report);
                        }
                }
        }
@@ -1899,6 +1913,83 @@ namespace Mono.CSharp {
                        return LookupTypeContainer (t);
                }
 
+               public static Variance GetTypeParameterVariance (Type type)
+               {
+                       TypeParameter tparam = LookupTypeParameter (type);
+                       if (tparam != null)
+                               return tparam.Variance;
+
+                       switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) {
+                       case GenericParameterAttributes.Covariant:
+                               return Variance.Covariant;
+                       case GenericParameterAttributes.Contravariant:
+                               return Variance.Contravariant;
+                       default:
+                               return Variance.None;
+                       }
+               }
+
+               public static Variance CheckTypeVariance (Type t, Variance expected, IMemberContext member)
+               {
+                       TypeParameter tp = LookupTypeParameter (t);
+                       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)
+                                       tp.ErrorInvalidVariance (member, expected);
+
+                               return expected;
+                       }
+
+                       if (t.IsGenericType) {
+                               Type[] targs_definition = GetTypeArguments (DropGenericTypeArguments (t));
+                               Type[] targs = GetTypeArguments (t);
+                               for (int i = 0; i < targs_definition.Length; ++i) {
+                                       Variance v = GetTypeParameterVariance (targs_definition[i]);
+                                       CheckTypeVariance (targs[i], (Variance) ((int)v * (int)expected), member);
+                               }
+
+                               return expected;
+                       }
+
+                       if (t.IsArray)
+                               return CheckTypeVariance (GetElementType (t), expected, member);
+
+                       return Variance.None;
+               }
+
+               public static bool IsVariantOf (Type type1, Type type2)
+               {
+                       if (!type1.IsGenericType || !type2.IsGenericType)
+                               return false;
+
+                       Type generic_target_type = DropGenericTypeArguments (type2);
+                       if (DropGenericTypeArguments (type1) != generic_target_type)
+                               return false;
+
+                       Type[] t1 = GetTypeArguments (type1);
+                       Type[] t2 = GetTypeArguments (type2);
+                       Type[] targs_definition = GetTypeArguments (generic_target_type);
+                       for (int i = 0; i < targs_definition.Length; ++i) {
+                               Variance v = GetTypeParameterVariance (targs_definition [i]);
+                               if (v == Variance.None) {
+                                       if (t1[i] == t2[i])
+                                               continue;
+                                       return false;
+                               }
+
+                               if (v == Variance.Covariant) {
+                                       if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1 [i]), t2 [i]))
+                                               return false;
+                               } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2[i]), t1[i])) {
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+
                /// <summary>
                ///   Check whether `a' and `b' may become equal generic types.
                ///   The algorithm to do that is a little bit complicated.
@@ -1912,7 +2003,7 @@ namespace Mono.CSharp {
                                // become equal.
                                //
                                while (b.IsArray) {
-                                       b = b.GetElementType ();
+                                       b = GetElementType (b);
                                        if (a.Equals (b))
                                                return false;
                                }
@@ -1980,8 +2071,8 @@ namespace Mono.CSharp {
                                if (a.GetArrayRank () != b.GetArrayRank ())
                                        return false;
                        
-                               a = a.GetElementType ();
-                               b = b.GetElementType ();
+                               a = GetElementType (a);
+                               b = GetElementType (b);
 
                                return MayBecomeEqualGenericTypes (a, b, class_inferred, method_inferred);
                        }
@@ -2031,9 +2122,7 @@ namespace Mono.CSharp {
                ///   when resolving an Invocation or a DelegateInvocation and the user
                ///   did not explicitly specify type arguments.
                /// </summary>
-               public static int InferTypeArguments (EmitContext ec,
-                                                      ArrayList arguments,
-                                                      ref MethodBase method)
+               public static int InferTypeArguments (ResolveContext ec, Arguments arguments, ref MethodBase method)
                {
                        ATypeInference ti = ATypeInference.CreateInstance (arguments);
                        Type[] i_args = ti.InferMethodArguments (ec, method);
@@ -2047,43 +2136,38 @@ namespace Mono.CSharp {
                        return 0;
                }
 
-               /// <summary>
-               ///   Type inference.
-               /// </summary>
-               public static bool InferTypeArguments (AParametersCollection apd,
-                                                      ref MethodBase method)
+/*
+               public static bool InferTypeArguments (ResolveContext ec, AParametersCollection param, ref MethodBase method)
                {
                        if (!TypeManager.IsGenericMethod (method))
                                return true;
 
-                       ATypeInference ti = ATypeInference.CreateInstance (ArrayList.Adapter (apd.Types));
-                       Type[] i_args = ti.InferDelegateArguments (method);
+                       ATypeInference ti = ATypeInference.CreateInstance (DelegateCreation.CreateDelegateMethodArguments (param, Location.Null));
+                       Type[] i_args = ti.InferDelegateArguments (ec, method);
                        if (i_args == null)
                                return false;
 
                        method = ((MethodInfo) method).MakeGenericMethod (i_args);
                        return true;
                }
+*/
        }
 
        abstract class ATypeInference
        {
-               protected readonly ArrayList arguments;
+               protected readonly Arguments arguments;
                protected readonly int arg_count;
 
-               protected ATypeInference (ArrayList arguments)
+               protected ATypeInference (Arguments arguments)
                {
                        this.arguments = arguments;
                        if (arguments != null)
                                arg_count = arguments.Count;
                }
 
-               public static ATypeInference CreateInstance (ArrayList arguments)
+               public static ATypeInference CreateInstance (Arguments arguments)
                {
-                       if (RootContext.Version == LanguageVersion.ISO_2)
-                               return new TypeInferenceV2 (arguments);
-
-                       return new TypeInferenceV3 (arguments);
+                       return new TypeInference (arguments);
                }
 
                public virtual int InferenceScore {
@@ -2092,193 +2176,21 @@ namespace Mono.CSharp {
                        }
                }
 
-               public abstract Type[] InferMethodArguments (EmitContext ec, MethodBase method);
-               public abstract Type[] InferDelegateArguments (MethodBase method);
-       }
-
-       //
-       // Implements C# 2.0 type inference
-       //
-       class TypeInferenceV2 : ATypeInference
-       {
-               public TypeInferenceV2 (ArrayList arguments)
-                       : base (arguments)
-               {
-               }
-
-               public override Type[] InferDelegateArguments (MethodBase method)
-               {
-                       AParametersCollection pd = TypeManager.GetParameterData (method);
-                       if (arg_count != pd.Count)
-                               return null;
-
-                       Type[] method_args = method.GetGenericArguments ();
-                       Type[] inferred_types = new Type[method_args.Length];
-
-                       Type[] param_types = new Type[pd.Count];
-                       Type[] arg_types = (Type[])arguments.ToArray (typeof (Type));
-
-                       for (int i = 0; i < arg_count; i++) {
-                               param_types[i] = pd.Types [i];
-                       }
-
-                       if (!InferTypeArguments (param_types, arg_types, inferred_types))
-                               return null;
-
-                       return inferred_types;
-               }
-
-               public override Type[] InferMethodArguments (EmitContext ec, MethodBase 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];
-
-                       int a_count = arg_types.Length;
-                       if (pd.HasParams)
-                               --a_count;
-
-                       for (int i = 0; i < a_count; i++) {
-                               Argument a = (Argument) arguments[i];
-                               if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
-                                       continue;
-
-                               if (!TypeInferenceV2.UnifyType (pd.Types [i], a.Type, inferred_types))
-                                       return null;
-                       }
-
-                       if (pd.HasParams) {
-                               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)
-                                               continue;
-
-                                       if (!TypeInferenceV2.UnifyType (element_type, a.Type, inferred_types))
-                                               return null;
-                               }
-                       }
-
-                       for (int i = 0; i < inferred_types.Length; i++)
-                               if (inferred_types [i] == null)
-                                       return null;
-
-                       return inferred_types;
-               }
-
-               static bool InferTypeArguments (Type[] param_types, Type[] arg_types,
-                               Type[] inferred_types)
-               {
-                       for (int i = 0; i < arg_types.Length; i++) {
-                               if (arg_types[i] == null)
-                                       continue;
-
-                               if (!UnifyType (param_types[i], arg_types[i], inferred_types))
-                                       return false;
-                       }
-
-                       for (int i = 0; i < inferred_types.Length; ++i)
-                               if (inferred_types[i] == null)
-                                       return false;
-
-                       return true;
-               }
-
-               public static bool UnifyType (Type pt, Type at, Type[] inferred)
-               {
-                       if (pt.IsGenericParameter) {
-                               if (pt.DeclaringMethod == null)
-                                       return pt == at;
-
-                               int pos = pt.GenericParameterPosition;
-
-                               if (inferred [pos] == null)
-                                       inferred [pos] = at;
-
-                               return inferred [pos] == at;
-                       }
-
-                       if (!pt.ContainsGenericParameters) {
-                               if (at.ContainsGenericParameters)
-                                       return UnifyType (at, pt, inferred);
-                               else
-                                       return true;
-                       }
-
-                       if (at.IsArray) {
-                               if (pt.IsArray) {
-                                       if (at.GetArrayRank () != pt.GetArrayRank ())
-                                               return false;
-
-                                       return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
-                               }
-
-                               if (!pt.IsGenericType)
-                                       return false;
-
-                               Type gt = pt.GetGenericTypeDefinition ();
-                               if ((gt != TypeManager.generic_ilist_type) && (gt != TypeManager.generic_icollection_type) &&
-                                       (gt != TypeManager.generic_ienumerable_type))
-                                       return false;
-
-                               Type[] args = TypeManager.GetTypeArguments (pt);
-                               return UnifyType (args[0], at.GetElementType (), inferred);
-                       }
-
-                       if (pt.IsArray) {
-                               if (!at.IsArray ||
-                                       (pt.GetArrayRank () != at.GetArrayRank ()))
-                                       return false;
-
-                               return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
-                       }
-
-                       if (pt.IsByRef && at.IsByRef)
-                               return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
-                       ArrayList list = new ArrayList ();
-                       if (at.IsGenericType)
-                               list.Add (at);
-                       for (Type bt = at.BaseType; bt != null; bt = bt.BaseType)
-                               list.Add (bt);
-
-                       list.AddRange (TypeManager.GetInterfaces (at));
-
-                       foreach (Type type in list) {
-                               if (!type.IsGenericType)
-                                       continue;
-
-                               if (TypeManager.DropGenericTypeArguments (pt) != TypeManager.DropGenericTypeArguments (type))
-                                       continue;
-
-                               if (!UnifyTypes (pt.GetGenericArguments (), type.GetGenericArguments (), inferred))
-                                       return false;
-                       }
-
-                       return true;
-               }
-
-               static bool UnifyTypes (Type[] pts, Type[] ats, Type[] inferred)
-               {
-                       for (int i = 0; i < ats.Length; i++) {
-                               if (!UnifyType (pts [i], ats [i], inferred))
-                                       return false;
-                       }
-                       return true;
-               }
+               public abstract Type[] InferMethodArguments (ResolveContext ec, MethodBase method);
+//             public abstract Type[] InferDelegateArguments (ResolveContext ec, MethodBase method);
        }
 
        //
-       // Implements C# 3.0 type inference
+       // Implements C# type inference
        //
-       class TypeInferenceV3 : ATypeInference
+       class TypeInference : ATypeInference
        {
                //
                // Tracks successful rate of type inference
                //
                int score = int.MaxValue;
 
-               public TypeInferenceV3 (ArrayList arguments)
+               public TypeInference (Arguments arguments)
                        : base (arguments)
                {
                }
@@ -2289,7 +2201,8 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override Type[] InferDelegateArguments (MethodBase method)
+/*
+               public override Type[] InferDelegateArguments (ResolveContext ec, MethodBase method)
                {
                        AParametersCollection pd = TypeManager.GetParameterData (method);
                        if (arg_count != pd.Count)
@@ -2305,16 +2218,16 @@ namespace Mono.CSharp {
                                if (!t.IsGenericParameter)
                                        continue;
 
-                               context.LowerBoundInference ((Type)arguments[i], t);
+                               context.LowerBoundInference (arguments [i].Expr.Type, t);
                        }
 
-                       if (!context.FixAllTypes ())
+                       if (!context.FixAllTypes (ec))
                                return null;
 
                        return context.InferredTypeArguments;
                }
-
-               public override Type[] InferMethodArguments (EmitContext ec, MethodBase method)
+*/
+               public override Type[] InferMethodArguments (ResolveContext ec, MethodBase method)
                {
                        Type[] method_generic_args = method.GetGenericArguments ();
                        TypeInferenceContext context = new TypeInferenceContext (method_generic_args);
@@ -2331,7 +2244,7 @@ namespace Mono.CSharp {
                //
                // Implements method type arguments inference
                //
-               bool InferInPhases (EmitContext ec, TypeInferenceContext tic, AParametersCollection methodParameters)
+               bool InferInPhases (ResolveContext ec, TypeInferenceContext tic, AParametersCollection methodParameters)
                {
                        int params_arguments_start;
                        if (methodParameters.HasParams) {
@@ -2347,7 +2260,9 @@ namespace Mono.CSharp {
                        //
                        Type method_parameter = null;
                        for (int i = 0; i < arg_count; i++) {
-                               Argument a = (Argument) arguments [i];
+                               Argument a = arguments [i];
+                               if (a == null)
+                                       continue;
                                
                                if (i < params_arguments_start) {
                                        method_parameter = methodParameters.Types [i];
@@ -2367,14 +2282,24 @@ namespace Mono.CSharp {
                                //
                                AnonymousMethodExpression am = a.Expr as AnonymousMethodExpression;
                                if (am != null) {
-                                       if (am.ExplicitTypeInference (tic, method_parameter))
+                                       if (am.ExplicitTypeInference (ec, tic, method_parameter))
                                                --score; 
                                        continue;
                                }
 
-                               if (a.Expr is NullLiteral)
+                               if (a.IsByRef) {
+                                       score -= tic.ExactInference (a.Type, method_parameter);
+                                       continue;
+                               }
+
+                               if (a.Expr.Type == TypeManager.null_type)
                                        continue;
 
+                               if (TypeManager.IsValueType (method_parameter)) {
+                                       score -= tic.LowerBoundInference (a.Type, method_parameter);
+                                       continue;
+                               }
+
                                //
                                // Otherwise an output type inference is made
                                //
@@ -2386,16 +2311,16 @@ namespace Mono.CSharp {
                        // we don't need to call it in cycle
                        //
                        bool fixed_any = false;
-                       if (!tic.FixIndependentTypeArguments (ptypes, ref fixed_any))
+                       if (!tic.FixIndependentTypeArguments (ec, ptypes, ref fixed_any))
                                return false;
 
                        return DoSecondPhase (ec, tic, ptypes, !fixed_any);
                }
 
-               bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, Type[] methodParameters, bool fixDependent)
+               bool DoSecondPhase (ResolveContext ec, TypeInferenceContext tic, Type[] methodParameters, bool fixDependent)
                {
                        bool fixed_any = false;
-                       if (fixDependent && !tic.FixDependentTypes (ref fixed_any))
+                       if (fixDependent && !tic.FixDependentTypes (ec, ref fixed_any))
                                return false;
 
                        // If no further unfixed type variables exist, type inference succeeds
@@ -2420,7 +2345,7 @@ namespace Mono.CSharp {
                                        t_i = t_i.GetGenericArguments () [0];
                                }
 
-                               MethodInfo mi = Delegate.GetInvokeMethod (t_i, t_i);
+                               MethodInfo mi = Delegate.GetInvokeMethod (ec.Compiler, t_i, t_i);
                                Type rtype = mi.ReturnType;
 
 #if MS_COMPATIBLE
@@ -2429,8 +2354,8 @@ namespace Mono.CSharp {
                                rtype = g_args[rtype.GenericParameterPosition];
 #endif
 
-                               if (tic.IsReturnTypeNonDependent (mi, rtype))
-                                       score -= tic.OutputTypeInference (ec, ((Argument) arguments [i]).Expr, t_i);
+                               if (tic.IsReturnTypeNonDependent (ec, mi, rtype))
+                                       score -= tic.OutputTypeInference (ec, arguments [i].Expr, t_i);
                        }
 
 
@@ -2440,6 +2365,36 @@ namespace Mono.CSharp {
 
        public class TypeInferenceContext
        {
+               enum BoundKind
+               {
+                       Exact   = 0,
+                       Lower   = 1,
+                       Upper   = 2
+               }
+
+               class BoundInfo
+               {
+                       public readonly Type Type;
+                       public readonly BoundKind Kind;
+
+                       public BoundInfo (Type type, BoundKind kind)
+                       {
+                               this.Type = type;
+                               this.Kind = kind;
+                       }
+                       
+                       public override int GetHashCode ()
+                       {
+                               return Type.GetHashCode ();
+                       }
+
+                       public override bool Equals (object obj)
+                       {
+                               BoundInfo a = (BoundInfo) obj;
+                               return Type == a.Type && Kind == a.Kind;
+                       }
+               }
+
                readonly Type[] unfixed_types;
                readonly Type[] fixed_types;
                readonly ArrayList[] bounds;
@@ -2464,18 +2419,35 @@ namespace Mono.CSharp {
                        }
                }
 
+               // 
+               // Used together with AddCommonTypeBound fo implement
+               // 7.4.2.13 Finding the best common type of a set of expressions
+               //
+               public TypeInferenceContext ()
+               {
+                       fixed_types = new Type [1];
+                       unfixed_types = new Type [1];
+                       unfixed_types[0] = InternalType.Arglist; // it can be any internal type
+                       bounds = new ArrayList [1];
+               }
+
                public Type[] InferredTypeArguments {
                        get {
                                return fixed_types;
                        }
                }
 
-               void AddToBounds (Type t, int index)
+               public void AddCommonTypeBound (Type type)
+               {
+                       AddToBounds (new BoundInfo (type, BoundKind.Lower), 0);
+               }
+
+               void AddToBounds (BoundInfo bound, int index)
                {
                        //
                        // Some types cannot be used as type arguments
                        //
-                       if (t == TypeManager.void_type || t.IsPointer)
+                       if (bound.Type == TypeManager.void_type || bound.Type.IsPointer)
                                return;
 
                        ArrayList a = bounds [index];
@@ -2483,7 +2455,7 @@ namespace Mono.CSharp {
                                a = new ArrayList ();
                                bounds [index] = a;
                        } else {
-                               if (a.Contains (t))
+                               if (a.Contains (bound))
                                        return;
                        }
 
@@ -2497,7 +2469,7 @@ namespace Mono.CSharp {
                        //        //    t = constraints.EffectiveBaseClass;
                        //    }
                        //}
-                       a.Add (t);
+                       a.Add (bound);
                }
                
                bool AllTypesAreFixed (Type[] types)
@@ -2554,14 +2526,14 @@ namespace Mono.CSharp {
                        if (pos == -1)
                                return 0;
 
-                       AddToBounds (u, pos);
+                       AddToBounds (new BoundInfo (u, BoundKind.Exact), pos);
                        return 1;
                }
 
-               public bool FixAllTypes ()
+               public bool FixAllTypes (ResolveContext ec)
                {
                        for (int i = 0; i < unfixed_types.Length; ++i) {
-                               if (!FixType (i))
+                               if (!FixType (ec, i))
                                        return false;
                        }
                        return true;
@@ -2572,7 +2544,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 (ref bool fixed_any)
+               public bool FixDependentTypes (ResolveContext ec, ref bool fixed_any)
                {
                        for (int i = 0; i < unfixed_types.Length; ++i) {
                                if (unfixed_types[i] == null)
@@ -2581,7 +2553,7 @@ namespace Mono.CSharp {
                                if (bounds[i] == null)
                                        continue;
 
-                               if (!FixType (i))
+                               if (!FixType (ec, i))
                                        return false;
                                
                                fixed_any = true;
@@ -2593,13 +2565,11 @@ namespace Mono.CSharp {
                //
                // All unfixed type variables Xi which depend on no Xj are fixed
                //
-               public bool FixIndependentTypeArguments (Type[] methodParameters, ref bool fixed_any)
+               public bool FixIndependentTypeArguments (ResolveContext ec, Type[] methodParameters, ref bool fixed_any)
                {
                        ArrayList types_to_fix = new ArrayList (unfixed_types);
                        for (int i = 0; i < methodParameters.Length; ++i) {
                                Type t = methodParameters[i];
-                               if (t.IsGenericParameter)
-                                       continue;
 
                                if (!TypeManager.IsDelegateType (t)) {
                                        if (TypeManager.DropGenericTypeArguments (t) != TypeManager.expression_type)
@@ -2608,7 +2578,10 @@ namespace Mono.CSharp {
                                        t = t.GetGenericArguments () [0];
                                }
 
-                               MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
+                               if (t.IsGenericParameter)
+                                       continue;
+
+                               MethodInfo invoke = Delegate.GetInvokeMethod (ec.Compiler, t, t);
                                Type rtype = invoke.ReturnType;
                                if (!rtype.IsGenericParameter && !rtype.IsGenericType)
                                        continue;
@@ -2629,7 +2602,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                int idx = IsUnfixed (t);
-                               if (idx >= 0 && !FixType (idx)) {
+                               if (idx >= 0 && !FixType (ec, idx)) {
                                        return false;
                                }
                        }
@@ -2641,7 +2614,7 @@ namespace Mono.CSharp {
                //
                // 26.3.3.10 Fixing
                //
-               public bool FixType (int i)
+               public bool FixType (ResolveContext ec, int i)
                {
                        // It's already fixed
                        if (unfixed_types[i] == null)
@@ -2656,7 +2629,11 @@ namespace Mono.CSharp {
 
                        if (candidates.Count == 1) {
                                unfixed_types[i] = null;
-                               fixed_types[i] = (Type)candidates[0];
+                               Type t = ((BoundInfo) candidates[0]).Type;
+                               if (t == TypeManager.null_type)
+                                       return false;
+
+                               fixed_types [i] = t;
                                return true;
                        }
 
@@ -2669,24 +2646,60 @@ namespace Mono.CSharp {
                        int cii;
                        int candidates_count = candidates.Count;
                        for (int ci = 0; ci < candidates_count; ++ci) {
-                               Type candidate = (Type)candidates [ci];
+                               BoundInfo bound = (BoundInfo)candidates [ci];
                                for (cii = 0; cii < candidates_count; ++cii) {
                                        if (cii == ci)
                                                continue;
 
-                                       if (!Convert.ImplicitConversionExists (null,
-                                               new TypeExpression ((Type)candidates [cii], Location.Null), candidate)) {
+                                       BoundInfo cbound = (BoundInfo) candidates[cii];
+                                       
+                                       // Same type parameters with different bounds
+                                       if (cbound.Type == bound.Type) {
+                                               if (bound.Kind != BoundKind.Exact)
+                                                       bound = cbound;
+
+                                               continue;
+                                       }
+
+                                       if (bound.Kind == BoundKind.Exact || cbound.Kind == BoundKind.Exact) {
+                                               if (cbound.Kind != BoundKind.Exact) {
+                                                       if (!Convert.ImplicitConversionExists (ec, new TypeExpression (cbound.Type, Location.Null), bound.Type)) {
+                                                               break;
+                                                       }
+
+                                                       continue;
+                                               }
+                                               
+                                               if (bound.Kind != BoundKind.Exact) {
+                                                       if (!Convert.ImplicitConversionExists (ec, new TypeExpression (bound.Type, Location.Null), cbound.Type)) {
+                                                               break;
+                                                       }
+
+                                                       bound = cbound;
+                                                       continue;
+                                               }
+                                               
                                                break;
                                        }
+
+                                       if (bound.Kind == BoundKind.Lower) {
+                                               if (!Convert.ImplicitConversionExists (ec, new TypeExpression (cbound.Type, Location.Null), bound.Type)) {
+                                                       break;
+                                               }
+                                       } else {
+                                               if (!Convert.ImplicitConversionExists (ec, new TypeExpression (bound.Type, Location.Null), cbound.Type)) {
+                                                       break;
+                                               }
+                                       }
                                }
 
                                if (cii != candidates_count)
                                        continue;
 
-                               if (best_candidate != null)
+                               if (best_candidate != null && best_candidate != bound.Type)
                                        return false;
 
-                               best_candidate = candidate;
+                               best_candidate = bound.Type;
                        }
 
                        if (best_candidate == null)
@@ -2727,15 +2740,15 @@ namespace Mono.CSharp {
                // Tests whether all delegate input arguments are fixed and generic output type
                // requires output type inference 
                //
-               public bool IsReturnTypeNonDependent (MethodInfo invoke, Type returnType)
+               public bool IsReturnTypeNonDependent (ResolveContext ec, MethodInfo invoke, Type returnType)
                {
                        if (returnType.IsGenericParameter) {
                                if (IsFixed (returnType))
                                    return false;
                        } else if (returnType.IsGenericType) {
                                if (TypeManager.IsDelegateType (returnType)) {
-                                       invoke = Delegate.GetInvokeMethod (returnType, returnType);
-                                       return IsReturnTypeNonDependent (invoke, invoke.ReturnType);
+                                       invoke = Delegate.GetInvokeMethod (ec.Compiler, returnType, returnType);
+                                       return IsReturnTypeNonDependent (ec, invoke, invoke.ReturnType);
                                }
                                        
                                Type[] g_args = returnType.GetGenericArguments ();
@@ -2775,31 +2788,38 @@ namespace Mono.CSharp {
                // 26.3.3.9 Lower-bound Inference
                //
                public int LowerBoundInference (Type u, Type v)
+               {
+                       return LowerBoundInference (u, v, false);
+               }
+
+               //
+               // Lower-bound (false) or Upper-bound (true) inference based on inversed argument
+               //
+               int LowerBoundInference (Type u, Type v, bool inversed)
                {
                        // If V is one of the unfixed type arguments
                        int pos = IsUnfixed (v);
                        if (pos != -1) {
-                               AddToBounds (u, pos);
+                               AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos);
                                return 1;
                        }                       
 
                        // If U is an array type
                        if (u.IsArray) {
                                int u_dim = u.GetArrayRank ();
-                               Type v_e;
-                               Type u_e = TypeManager.GetElementType (u);
+                               Type v_i;
+                               Type u_i = TypeManager.GetElementType (u);
 
                                if (v.IsArray) {
                                        if (u_dim != v.GetArrayRank ())
                                                return 0;
 
-                                       v_e = TypeManager.GetElementType (v);
+                                       v_i = TypeManager.GetElementType (v);
 
-                                       if (u.IsByRef) {
-                                               return LowerBoundInference (u_e, v_e);
-                                       }
+                                       if (TypeManager.IsValueType (u_i))
+                                               return ExactInference (u_i, v_i);
 
-                                       return ExactInference (u_e, v_e);
+                                       return LowerBoundInference (u_i, v_i, inversed);
                                }
 
                                if (u_dim != 1)
@@ -2811,19 +2831,17 @@ namespace Mono.CSharp {
                                                (g_v != TypeManager.generic_ienumerable_type))
                                                return 0;
 
-                                       v_e = TypeManager.GetTypeArguments (v)[0];
+                                       v_i = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (v) [0]);
+                                       if (TypeManager.IsValueType (u_i))
+                                               return ExactInference (u_i, v_i);
 
-                                       if (u.IsByRef) {
-                                               return LowerBoundInference (u_e, v_e);
-                                       }
-
-                                       return ExactInference (u_e, v_e);
+                                       return LowerBoundInference (u_i, v_i);
                                }
                        } else if (v.IsGenericType && !v.IsGenericTypeDefinition) {
                                //
-                               // if V is a constructed type C<V1..Vk> and there is a unique set of types U1..Uk
-                               // such that a standard implicit conversion exists from U to C<U1..Uk> then an exact
-                               // inference is made from each Ui for the corresponding Vi
+                               // if V is a constructed type C<V1..Vk> and there is a unique type C<U1..Uk>
+                               // such that U is identical to, inherits from (directly or indirectly),
+                               // or implements (directly or indirectly) C<U1..Uk>
                                //
                                ArrayList u_candidates = new ArrayList ();
                                if (u.IsGenericType)
@@ -2849,9 +2867,9 @@ namespace Mono.CSharp {
                                                continue;
 
                                        //
-                                       // 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
+                                       // The unique set of types U1..Uk means that if we have an interface I<T>,
+                                       // class U : I<int>, I<long> then no type inference is made when inferring
+                                       // type I<T> by applying type U because T could be int or long
                                        //
                                        if (unique_candidate_targs != null) {
                                                Type[] second_unique_candidate_targs = u_candidate.GetGenericArguments ();
@@ -2859,7 +2877,7 @@ namespace Mono.CSharp {
                                                        unique_candidate_targs = second_unique_candidate_targs;
                                                        continue;
                                                }
-                                               
+
                                                //
                                                // This should always cause type inference failure
                                                //
@@ -2871,10 +2889,23 @@ namespace Mono.CSharp {
                                }
 
                                if (unique_candidate_targs != null) {
+                                       Type[] ga_open_v = open_v.GetGenericArguments ();
                                        int score = 0;
-                                       for (int i = 0; i < unique_candidate_targs.Length; ++i)
-                                               if (ExactInference (unique_candidate_targs [i], ga_v [i]) == 0)
-                                                       ++score;
+                                       for (int i = 0; i < unique_candidate_targs.Length; ++i) {
+                                               Variance variance = TypeManager.GetTypeParameterVariance (ga_open_v [i]);
+
+                                               Type u_i = unique_candidate_targs [i];
+                                               if (variance == Variance.None || TypeManager.IsValueType (u_i)) {
+                                                       if (ExactInference (u_i, ga_v [i]) == 0)
+                                                               ++score;
+                                               } else {
+                                                       bool upper_bound = (variance == Variance.Contravariant && !inversed) ||
+                                                               (variance == Variance.Covariant && inversed);
+
+                                                       if (LowerBoundInference (u_i, ga_v [i], upper_bound) == 0)
+                                                               ++score;
+                                               }
+                                       }
                                        return score;
                                }
                        }
@@ -2885,13 +2916,13 @@ namespace Mono.CSharp {
                //
                // 26.3.3.6 Output Type Inference
                //
-               public int OutputTypeInference (EmitContext ec, Expression e, Type t)
+               public int OutputTypeInference (ResolveContext ec, Expression e, Type t)
                {
                        // If e is a lambda or anonymous method with inferred return type
                        AnonymousMethodExpression ame = e as AnonymousMethodExpression;
                        if (ame != null) {
                                Type rt = ame.InferReturnType (ec, this, t);
-                               MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
+                               MethodInfo invoke = Delegate.GetInvokeMethod (ec.Compiler, t, t);
 
                                if (rt == null) {
                                        AParametersCollection pd = TypeManager.GetParameterData (invoke);
@@ -2918,7 +2949,7 @@ namespace Mono.CSharp {
                                if (!TypeManager.IsDelegateType (t))
                                        return 0;
 
-                               MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
+                               MethodInfo invoke = Delegate.GetInvokeMethod (ec.Compiler, t, t);
                                Type rtype = invoke.ReturnType;
 #if MS_COMPATIBLE
                                // Blablabla, because reflection does not work with dynamic types
@@ -2930,7 +2961,7 @@ namespace Mono.CSharp {
                                        return 0;
 
                                MethodGroupExpr mg = (MethodGroupExpr) e;
-                               ArrayList args = DelegateCreation.CreateDelegateMethodArguments (invoke, e.Location);
+                               Arguments args = DelegateCreation.CreateDelegateMethodArguments (TypeManager.GetParameterData (invoke), e.Location);
                                mg = mg.OverloadResolve (ec, ref args, true, e.Location);
                                if (mg == null)
                                        return 0;
@@ -2947,10 +2978,11 @@ namespace Mono.CSharp {
                        return LowerBoundInference (e.Type, t) * 2;
                }
 
-               static void RemoveDependentTypes (ArrayList types, Type returnType)
+               void RemoveDependentTypes (ArrayList types, Type returnType)
                {
-                       if (returnType.IsGenericParameter) {
-                               types [returnType.GenericParameterPosition] = null;
+                       int idx = IsUnfixed (returnType);
+                       if (idx >= 0) {
+                               types [idx] = null;
                                return;
                        }