2009-02-16 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / generic.cs
index b83cb535f1cbf148421cda4e16d2c2bbc0c082a6..9bdcc1d77fc33725dde6203eae64c7e32a2ca3c8 100644 (file)
@@ -5,10 +5,10 @@
 //          Miguel de Icaza (miguel@ximian.com)
 //          Marek Safar (marek.safar@gmail.com)
 //
-// Licensed under the terms of the GNU GPL
+// Dual licensed under the terms of the MIT X11 or GNU GPL
 //
-// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
-// (C) 2004 Novell, Inc
+// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+// Copyright 2004-2008 Novell, Inc
 //
 using System;
 using System.Reflection;
@@ -124,6 +124,13 @@ namespace Mono.CSharp {
                }
        }
 
+       public enum Variance
+       {
+               None,
+               Covariant,
+               Contravariant
+       }
+
        public enum SpecialConstraint
        {
                Constructor,
@@ -182,7 +189,7 @@ namespace Mono.CSharp {
                        if (resolved)
                                return true;
 
-                       iface_constraints = new ArrayList ();
+                       iface_constraints = new ArrayList (2);  // TODO: Too expensive allocation
                        type_param_constraints = new ArrayList ();
 
                        foreach (object obj in constraints) {
@@ -231,12 +238,9 @@ namespace Mono.CSharp {
                                }
 
                                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);
 
@@ -256,11 +260,10 @@ namespace Mono.CSharp {
                                        type_param_constraints.Add (expr);
                                else if (expr.IsInterface)
                                        iface_constraints.Add (expr);
-                               else if (class_constraint != null) {
+                               else if (class_constraint != null || iface_constraints.Count != 0) {
                                        Report.Error (406, loc,
-                                                     "`{0}': the class constraint for `{1}' " +
-                                                     "must come before any other constraints.",
-                                                     expr.Name, name);
+                                               "The class type constraint `{0}' must be listed before any other constraints. Consider moving type constraint to the beginning of the constraint list",
+                                               expr.GetSignatureForError ());
                                        return false;
                                } else if (HasReferenceTypeConstraint || HasValueTypeConstraint) {
                                        Report.Error (450, loc, "`{0}': cannot specify both " +
@@ -345,26 +348,52 @@ namespace Mono.CSharp {
                        else
                                effective_base_type = TypeManager.object_type;
 
+                       if ((attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
+                               attrs |= GenericParameterAttributes.DefaultConstructorConstraint;
+
                        resolved = true;
                        return true;
                }
 
-               bool CheckTypeParameterConstraints (TypeParameter tparam, Hashtable seen)
+               bool CheckTypeParameterConstraints (TypeParameter tparam, ref TypeExpr prevConstraint, ArrayList seen)
                {
-                       seen.Add (tparam, true);
+                       seen.Add (tparam);
 
                        Constraints constraints = tparam.Constraints;
                        if (constraints == null)
                                return true;
 
                        if (constraints.HasValueTypeConstraint) {
-                               Report.Error (456, loc, "Type parameter `{0}' has " +
-                                             "the `struct' constraint, so it cannot " +
-                                             "be used as a constraint for `{1}'",
-                                             tparam.Name, name);
+                               Report.Error (456, loc,
+                                       "Type parameter `{0}' has the `struct' constraint, so it cannot be used as a constraint for `{1}'",
+                                       tparam.Name, name);
                                return false;
                        }
 
+                       //
+                       //  Checks whether there are no conflicts between type parameter constraints
+                       //
+                       //   class Foo<T, U>
+                       //      where T : A
+                       //      where U : A, B  // A and B are not convertible
+                       //
+                       if (constraints.HasClassConstraint) {
+                               if (prevConstraint != null) {
+                                       Type t2 = constraints.ClassConstraint;
+                                       TypeExpr e2 = constraints.class_constraint;
+
+                                       if (!Convert.ImplicitReferenceConversionExists (prevConstraint, t2) &&
+                                               !Convert.ImplicitReferenceConversionExists (e2, prevConstraint.Type)) {
+                                               Report.Error (455, loc,
+                                                       "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'",
+                                                       name, TypeManager.CSharpName (prevConstraint.Type), TypeManager.CSharpName (t2));
+                                               return false;
+                                       }
+                               }
+
+                               prevConstraint = constraints.class_constraint;
+                       }
+
                        if (constraints.type_param_constraints == null)
                                return true;
 
@@ -372,11 +401,11 @@ namespace Mono.CSharp {
                                if (seen.Contains (expr.TypeParameter)) {
                                        Report.Error (454, loc, "Circular constraint " +
                                                      "dependency involving `{0}' and `{1}'",
-                                                     tparam.Name, expr.Name);
+                                                     tparam.Name, expr.GetSignatureForError ());
                                        return false;
                                }
 
-                               if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
+                               if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prevConstraint, seen))
                                        return false;
                        }
 
@@ -394,7 +423,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;
 
@@ -402,10 +431,14 @@ namespace Mono.CSharp {
                                        return false;
                        }
 
-                       foreach (TypeParameterExpr expr in type_param_constraints) {
-                               Hashtable seen = new Hashtable ();
-                               if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
-                                       return false;
+                       if (type_param_constraints.Count != 0) {
+                               ArrayList seen = new ArrayList ();
+                               TypeExpr prev_constraint = class_constraint;
+                               foreach (TypeParameterExpr expr in type_param_constraints) {
+                                       if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prev_constraint, seen))
+                                               return false;
+                                       seen.Clear ();
+                               }
                        }
 
                        for (int i = 0; i < iface_constraints.Count; ++i) {
@@ -425,66 +458,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               /// <summary>
-               ///   Check whether there are no conflicts in our type parameter constraints.
-               ///
-               ///   This is an example:
-               ///
-               ///   class Foo<T,U>
-               ///      where T : class
-               ///      where U : T, struct
-               /// </summary>
-               public bool CheckDependencies ()
-               {
-                       foreach (TypeParameterExpr expr in type_param_constraints) {
-                               if (!CheckDependencies (expr.TypeParameter))
-                                       return false;
-                       }
-
-                       return true;
-               }
-
-               bool CheckDependencies (TypeParameter tparam)
-               {
-                       Constraints constraints = tparam.Constraints;
-                       if (constraints == null)
-                               return true;
-
-                       if (HasValueTypeConstraint && constraints.HasClassConstraint) {
-                               Report.Error (455, loc, "Type parameter `{0}' inherits " +
-                                             "conflicting constraints `{1}' and `{2}'",
-                                             name, TypeManager.CSharpName (constraints.ClassConstraint),
-                                             "System.ValueType");
-                               return false;
-                       }
-
-                       if (HasClassConstraint && constraints.HasClassConstraint) {
-                               Type t1 = ClassConstraint;
-                               TypeExpr e1 = class_constraint;
-                               Type t2 = constraints.ClassConstraint;
-                               TypeExpr e2 = constraints.class_constraint;
-
-                               if (!Convert.ImplicitReferenceConversionExists (e1, t2) &&
-                                   !Convert.ImplicitReferenceConversionExists (e2, t1)) {
-                                       Report.Error (455, loc,
-                                                     "Type parameter `{0}' inherits " +
-                                                     "conflicting constraints `{1}' and `{2}'",
-                                                     name, TypeManager.CSharpName (t1), TypeManager.CSharpName (t2));
-                                       return false;
-                               }
-                       }
-
-                       if (constraints.type_param_constraints == null)
-                               return true;
-
-                       foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
-                               if (!CheckDependencies (expr.TypeParameter))
-                                       return false;
-                       }
-
-                       return true;
-               }
-
                public override GenericParameterAttributes Attributes {
                        get { return attrs; }
                }
@@ -535,7 +508,7 @@ namespace Mono.CSharp {
                ///   method.  To do that, we're called on each of the implementing method's
                ///   type parameters.
                /// </summary>
-               public bool CheckInterfaceMethod (GenericConstraints gc)
+               public bool AreEqual (GenericConstraints gc)
                {
                        if (gc.Attributes != attrs)
                                return false;
@@ -604,22 +577,25 @@ namespace Mono.CSharp {
        /// </summary>
        public class TypeParameter : MemberCore, IMemberContainer
        {
-               string name;
+               static readonly string[] attribute_target = new string [] { "type parameter" };
+               
                DeclSpace decl;
                GenericConstraints gc;
                Constraints constraints;
-               Location loc;
                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.loc = loc;
+                       this.variance = variance;
+                       if (variance != Variance.None && !(decl is Interface) && !(decl is Delegate)) {
+                               Report.Error (-36, loc, "Generic variance can only be used with interfaces and delegates");
+                       }
                }
 
                public GenericConstraints GenericConstraints {
@@ -634,6 +610,10 @@ namespace Mono.CSharp {
                        get { return decl; }
                }
 
+               public Variance Variance {
+                       get { return variance; }
+               }
+
                public Type Type {
                        get { return type; }
                }
@@ -729,7 +709,7 @@ namespace Mono.CSharp {
 
                        if (implementing != null) {
                                if (is_override && (constraints != null)) {
-                                       Report.Error (460, loc,
+                                       Report.Error (460, Location,
                                                "`{0}': Cannot specify constraints for overrides or explicit interface implementation methods",
                                                TypeManager.CSharpSignature (builder));
                                        return false;
@@ -750,7 +730,7 @@ namespace Mono.CSharp {
                                if (constraints != null) {
                                        if (temp_gc == null)
                                                ok = false;
-                                       else if (!constraints.CheckInterfaceMethod (gc))
+                                       else if (!constraints.AreEqual (gc))
                                                ok = false;
                                } else {
                                        if (!is_override && (temp_gc != null))
@@ -761,7 +741,7 @@ namespace Mono.CSharp {
                                        Report.SymbolRelatedToPreviousError (implementing);
 
                                        Report.Error (
-                                               425, loc, "The constraints for type " +
+                                               425, Location, "The constraints for type " +
                                                "parameter `{0}' of method `{1}' must match " +
                                                "the constraints for type parameter `{2}' " +
                                                "of interface method `{3}'. Consider using " +
@@ -782,34 +762,28 @@ namespace Mono.CSharp {
                                gc = (GenericConstraints) constraints;
                        }
 
-                       if (gc == null)
-                               return true;
-
-                       if (gc.HasClassConstraint)
-                               type.SetBaseTypeConstraint (gc.ClassConstraint);
-
-                       type.SetInterfaceConstraints (gc.InterfaceConstraints);
-                       type.SetGenericParameterAttributes (gc.Attributes);
-                       TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
-
+                       SetConstraints (type);
                        return true;
                }
 
-               /// <summary>
-               ///   Check whether there are no conflicts in our type parameter constraints.
-               ///
-               ///   This is an example:
-               ///
-               ///   class Foo<T,U>
-               ///      where T : class
-               ///      where U : T, struct
-               /// </summary>
-               public bool CheckDependencies ()
+               public void SetConstraints (GenericTypeParameterBuilder type)
                {
-                       if (constraints != null)
-                               return constraints.CheckDependencies ();
+                       GenericParameterAttributes attr = GenericParameterAttributes.None;
+                       if (variance == Variance.Contravariant)
+                               attr |= GenericParameterAttributes.Contravariant;
+                       else if (variance == Variance.Covariant)
+                               attr |= GenericParameterAttributes.Covariant;
 
-                       return true;
+                       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>
@@ -834,7 +808,7 @@ namespace Mono.CSharp {
                                return false;
 
                        if (constraints != null) 
-                               return constraints.CheckInterfaceMethod (new_constraints);
+                               return constraints.AreEqual (new_constraints);
 
                        constraints = new_constraints;
                        return true;
@@ -872,13 +846,13 @@ namespace Mono.CSharp {
 
                public override AttributeTargets AttributeTargets {
                        get {
-                               return (AttributeTargets) AttributeTargets.GenericParameter;
+                               return AttributeTargets.GenericParameter;
                        }
                }
 
                public override string[] ValidAttributeTargets {
                        get {
-                               return new string [] { "type parameter" };
+                               return attribute_target;
                        }
                }
 
@@ -908,7 +882,7 @@ namespace Mono.CSharp {
 
                MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
                {
-                       return FindMembers (mt, bf, null, null);
+                       throw new NotSupportedException ();
                }
 
                public MemberCache MemberCache {
@@ -963,26 +937,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)
@@ -1045,7 +999,7 @@ namespace Mono.CSharp {
                                if (t == null)
                                        return null;
                                if (t.IsGenericParameter)
-                                       return dargs [t.GenericParameterPosition];
+                                       return t.GenericParameterPosition < dargs.Length ? dargs [t.GenericParameterPosition] : t;
                                if (t.IsGenericType) {
                                        Type[] args = t.GetGenericArguments ();
                                        Type[] inflated = new Type [args.Length];
@@ -1088,18 +1042,6 @@ namespace Mono.CSharp {
        public class TypeParameterExpr : TypeExpr {
                TypeParameter type_parameter;
 
-               public override string Name {
-                       get {
-                               return type_parameter.Name;
-                       }
-               }
-
-               public override string FullName {
-                       get {
-                               return type_parameter.Name;
-                       }
-               }
-
                public TypeParameter TypeParameter {
                        get {
                                return type_parameter;
@@ -1114,8 +1056,13 @@ namespace Mono.CSharp {
 
                protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
                {
-                       type = type_parameter.Type;
+                       throw new NotSupportedException ();
+               }
 
+               public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
+               {
+                       type = type_parameter.Type;
+                       eclass = ExprClass.TypeParameter;
                        return this;
                }
 
@@ -1127,85 +1074,40 @@ namespace Mono.CSharp {
                {
                        return true;
                }
-
-               public void Error_CannotUseAsUnmanagedType (Location loc)
-               {
-                       Report.Error (-203, loc, "Can not use type parameter as unmanaged type");
-               }
        }
 
-       /// <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;
-               bool created;
                
-               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)
                {
-                       if (created)
-                               throw new InvalidOperationException ();
-
                        args.Add (type);
                }
 
                public void Add (TypeArguments new_args)
                {
-                       if (created)
-                               throw new InvalidOperationException ();
-
                        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) {
-                                       ret [i] = new TypeParameterName (sn.Name, null, sn.Location);
-                                       continue;
-                               }
-
-                               Report.Error (81, Location, "Type parameter declaration " +
-                                             "must be an identifier not a type");
-                               return null;
-                       }
-                       return ret;
+                       return (TypeParameterName[]) args.ToArray (typeof (TypeParameterName));
                }
 
                /// <summary>
@@ -1218,42 +1120,10 @@ 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;
-                       }
-               }
-
-               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 args.Count;
                        }
-                       return s.ToString ();
                }
 
                public string GetSignatureForError()
@@ -1274,48 +1144,46 @@ namespace Mono.CSharp {
                /// </summary>
                public bool Resolve (IResolveContext 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",
+                                       Report.Error (718, te.Location, "`{0}': static classes cannot be used as generic arguments",
                                                te.GetSignatureForError ());
-                                       return false;
-                               }
-
-                               if (te.Type.IsPointer) {
-                                       Report.Error (306, Location, "The type `{0}' may not be used " +
-                                                         "as a type argument", TypeManager.CSharpName (te.Type));
-                                       return false;
+                                       ok = false;
                                }
 
-                               if (te.Type == TypeManager.void_type) {
-                                       Expression.Error_VoidInvalidInTheContext (Location);
-                                       return false;
+                               if (te.Type.IsPointer || TypeManager.IsSpecialType (te.Type)) {
+                                       Report.Error (306, te.Location,
+                                               "The type `{0}' may not be used as a type argument",
+                                               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);
 
@@ -1326,11 +1194,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 {
@@ -1338,60 +1213,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 {
-               string full_name;
-               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;
-
-                       eclass = ExprClass.Type;
-                       full_name = name + "<" + args.ToString () + ">";
-               }
-
-               protected ConstructedType (TypeArguments args, Location l)
-               {
-                       loc = l;
-                       this.args = args;
-
-                       eclass = ExprClass.Type;
-               }
+               Type[] gen_params;      // TODO: Waiting for constrains check cleanup
+               Type open_type;
 
-               protected ConstructedType (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)
                {
-                       loc = l;
+                       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));
 
-                       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)
-                       : this (type_params, l)
-               {
-                       gt = t.GetGenericTypeDefinition ();
-
-                       this.name = new TypeExpression (gt, l);
-                       full_name = gt.FullName + "<" + args.ToString () + ">";
+                       this.loc = l;
                }
 
                /// <summary>
@@ -1399,13 +1252,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 (args, l)
+               public GenericTypeExpr (Type t, TypeArguments args, Location l)
                {
-                       gt = t.GetGenericTypeDefinition ();
+                       open_type = t.GetGenericTypeDefinition ();
 
-                       this.name = new TypeExpression (gt, l);
-                       full_name = gt.FullName + "<" + args.ToString () + ">";
+                       loc = l;
+                       this.args = args;
                }
 
                public TypeArguments TypeArguments {
@@ -1414,14 +1266,31 @@ namespace Mono.CSharp {
 
                public override string GetSignatureForError ()
                {
-                       return TypeManager.RemoveGenericArity (gt.FullName) + "<" + args.GetSignatureForError () + ">";
+                       return TypeManager.CSharpName (type);
                }
 
                protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
                {
-                       if (!ResolveConstructedType (ec))
+                       if (eclass != ExprClass.Invalid)
+                               return this;
+
+                       eclass = ExprClass.Type;
+
+                       if (!args.Resolve (ec))
+                               return null;
+
+                       gen_params = open_type.GetGenericArguments ();
+                       Type[] atypes = args.Arguments;
+                       
+                       if (atypes.Length != gen_params.Length) {
+                               Namespace.Error_InvalidNumberOfTypeArguments (open_type, loc);
                                return null;
+                       }
 
+                       //
+                       // Now bind the parameters
+                       //
+                       type = open_type.MakeGenericType (atypes);
                        return this;
                }
 
@@ -1431,107 +1300,79 @@ namespace Mono.CSharp {
                /// </summary>
                public bool CheckConstraints (IResolveContext ec)
                {
-                       return ConstraintChecker.CheckConstraints (ec, gt, gen_params, atypes, loc);
+                       return ConstraintChecker.CheckConstraints (ec, open_type, gen_params, args.Arguments, loc);
                }
 
-               /// <summary>
-               ///   Resolve the constructed type, but don't check the constraints.
-               /// </summary>
-               public bool ResolveConstructedType (IResolveContext ec)
+               static bool IsVariant (Type type)
                {
-                       if (type != null)
-                               return true;
-                       // If we already know the fully resolved generic type.
-                       if (gt != null)
-                               return DoResolveType (ec);
-
-                       int num_args;
-                       Type t = name.Type;
-
-                       if (t == null) {
-                               Report.Error (246, loc, "Cannot find type `{0}'<...>", Name);
-                               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);
+                       return (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) != 0;
                }
-
-               bool DoResolveType (IResolveContext ec)
+       
+               static bool IsCovariant (Type type)
                {
-                       //
-                       // Resolve the arguments.
-                       //
-                       if (args.Resolve (ec) == false)
-                               return false;
-
-                       gen_params = gt.GetGenericArguments ();
-                       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;
-                       }
-
-                       //
-                       // Now bind the parameters.
-                       //
-                       type = gt.MakeGenericType (atypes);
-                       return true;
+                       return (type.GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0;
                }
-
-               public Expression GetSimpleName (EmitContext ec)
+       
+               static bool IsContravariant (Type type)
                {
-                       return this;
+                       return (type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0;
+               }
+       
+               public bool VerifyVariantTypeParameters ()
+               {
+                       for (int i = 0; i < args.Count; i++) {
+                               Type argument = args.Arguments[i];
+                               if (argument.IsGenericParameter && IsVariant (argument)) {
+                                       if (IsContravariant (argument) && !IsContravariant (gen_params[i])) {
+                                               Report.Error (-34, loc, "Contravariant type parameters can only be used " +
+                                             "as type arguments in contravariant positions");
+                                               return false;
+                                       }
+                                       else if (IsCovariant (argument) && !IsCovariant (gen_params[i])) {
+                                               Report.Error (-35, loc, "Covariant type parameters can only be used " +
+                                             "as type arguments in covariant positions");
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
                }
 
+               
                public override bool CheckAccessLevel (DeclSpace ds)
                {
-                       return ds.CheckAccessLevel (gt);
+                       return ds.CheckAccessLevel (open_type);
                }
 
                public override bool AsAccessible (DeclSpace ds)
                {
-                       foreach (Type t in atypes) {
+                       foreach (Type t in args.Arguments) {
                                if (!ds.IsAccessibleAs (t))
                                        return false;
                        }
 
-                       return ds.IsAccessibleAs (gt);
+                       return ds.IsAccessibleAs (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;
 
@@ -1545,18 +1386,6 @@ namespace Mono.CSharp {
                {
                        return base.GetHashCode ();
                }
-
-               public override string Name {
-                       get {
-                               return full_name;
-                       }
-               }
-
-               public override string FullName {
-                       get {
-                               return full_name;
-                       }
-               }
        }
 
        public abstract class ConstraintChecker
@@ -1617,7 +1446,7 @@ namespace Mono.CSharp {
                                if (!atype.IsGenericType)
 #endif
                                is_class = atype.IsClass || atype.IsInterface;
-                               is_struct = atype.IsValueType && !TypeManager.IsNullableType (atype);
+                               is_struct = TypeManager.IsValueType (atype) && !TypeManager.IsNullableType (atype);
                        }
 
                        //
@@ -1668,7 +1497,7 @@ namespace Mono.CSharp {
                        if (!gc.HasConstructorConstraint)
                                return true;
 
-                       if (TypeManager.IsBuiltinType (atype) || atype.IsValueType)
+                       if (TypeManager.IsBuiltinType (atype) || TypeManager.IsValueType (atype))
                                return true;
 
                        if (HasDefaultConstructor (atype))
@@ -1692,7 +1521,7 @@ namespace Mono.CSharp {
                        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];
@@ -1704,29 +1533,58 @@ namespace Mono.CSharp {
                                        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))
                                return true;
 
-                       Error_TypeMustBeConvertible (expr.Type, ctype, ptype);
+                       Report_SymbolRelatedToPreviousError ();
+                       Report.SymbolRelatedToPreviousError (expr.Type);
+
+                       if (TypeManager.IsNullableType (expr.Type) && ctype.IsInterface) {
+                               Report.Error (313, loc,
+                                       "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. " +
+                                       "The nullable type `{0}' never satisfies interface constraint of type `{3}'",
+                                       TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ptype),
+                                       GetSignatureForError (), TypeManager.CSharpName (ctype));
+                       } else {
+                               Report.Error (309, loc,
+                                       "The type `{0}' must be convertible to `{1}' in order to " +
+                                       "use it as parameter `{2}' in the generic type or method `{3}'",
+                                       TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ctype),
+                                       TypeManager.CSharpName (ptype), GetSignatureForError ());
+                       }
                        return false;
                }
 
-               bool HasDefaultConstructor (Type atype)
+               static bool HasDefaultConstructor (Type atype)
                {
-                       if (atype.IsAbstract)
-                               return false;
-
-               again:
-                       atype = TypeManager.DropGenericTypeArguments (atype);
+                       TypeParameter tparam = TypeManager.LookupTypeParameter (atype);
+                       if (tparam != null) {
+                               if (tparam.GenericConstraints == null)
+                                       return false;
+                                               
+                               return tparam.GenericConstraints.HasConstructorConstraint || 
+                                       tparam.GenericConstraints.HasValueTypeConstraint;
+                       }
+               
+                       if (atype.IsAbstract)
+                               return false;
+
+               again:
+                       atype = TypeManager.DropGenericTypeArguments (atype);
                        if (atype is TypeBuilder) {
                                TypeContainer tc = TypeManager.LookupTypeContainer (atype);
                                if (tc.InstanceConstructors == null) {
@@ -1747,26 +1605,16 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       TypeParameter tparam = TypeManager.LookupTypeParameter (atype);
-                       if (tparam != null) {
-                               if (tparam.GenericConstraints == null)
-                                       return false;
-                                               
-                               return tparam.GenericConstraints.HasConstructorConstraint || 
-                                       tparam.GenericConstraints.HasValueTypeConstraint;
-                       }
+                       MemberInfo [] list = TypeManager.MemberLookup (null, null, atype, MemberTypes.Constructor,
+                               BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
+                               ConstructorInfo.ConstructorName, null);
 
-                       MemberList list = TypeManager.FindMembers (
-                               atype, MemberTypes.Constructor,
-                               BindingFlags.Public | BindingFlags.Instance |
-                               BindingFlags.DeclaredOnly, null, null);
-
-                       if (atype.IsAbstract || (list == null))
+                       if (list == null)
                                return false;
 
                        foreach (MethodBase mb in list) {
-                               ParameterData pd = TypeManager.GetParameterData (mb);
-                               if ((pd.Count == 0) && mb.IsPublic && !mb.IsStatic)
+                               AParametersCollection pd = TypeManager.GetParameterData (mb);
+                               if (pd.Count == 0)
                                        return true;
                        }
 
@@ -1776,17 +1624,6 @@ namespace Mono.CSharp {
                protected abstract string GetSignatureForError ();
                protected abstract void Report_SymbolRelatedToPreviousError ();
 
-               void Error_TypeMustBeConvertible (Type atype, Type gc, Type ptype)
-               {
-                       Report_SymbolRelatedToPreviousError ();
-                       Report.SymbolRelatedToPreviousError (atype);
-                       Report.Error (309, loc, 
-                                     "The type `{0}' must be convertible to `{1}' in order to " +
-                                     "use it as parameter `{2}' in the generic type or method `{3}'",
-                                     TypeManager.CSharpName (atype), TypeManager.CSharpName (gc),
-                                     TypeManager.CSharpName (ptype), GetSignatureForError ());
-               }
-
                public static bool CheckConstraints (EmitContext ec, MethodBase definition,
                                                     MethodBase instantiated, Location loc)
                {
@@ -1856,11 +1693,11 @@ namespace Mono.CSharp {
        /// </summary>
        public class GenericMethod : DeclSpace
        {
-               Expression return_type;
-               Parameters parameters;
+               FullNamedExpression return_type;
+               ParametersCompiled parameters;
 
                public GenericMethod (NamespaceEntry ns, DeclSpace parent, MemberName name,
-                                     Expression return_type, Parameters parameters)
+                                     FullNamedExpression return_type, ParametersCompiled parameters)
                        : base (ns, parent, name, null)
                {
                        this.return_type = return_type;
@@ -1885,22 +1722,26 @@ namespace Mono.CSharp {
                ///   Define and resolve the type parameters.
                ///   We're called from Method.Define().
                /// </summary>
-               public bool Define (MethodBuilder mb, ToplevelBlock block)
+               public bool Define (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 (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]);
 
@@ -1915,12 +1756,6 @@ 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>
@@ -1932,11 +1767,8 @@ namespace Mono.CSharp {
                                            ec, mb, implementing, is_override))
                                        return false;
 
-                       bool ok = true;
-                       foreach (Parameter p in parameters.FixedParameters){
-                               if (!p.Resolve (ec))
-                                       ok = false;
-                       }
+                       bool ok = parameters.Resolve (ec);
+
                        if ((return_type != null) && (return_type.ResolveAsTypeTerminal (ec, false) == null))
                                ok = false;
 
@@ -1952,11 +1784,6 @@ namespace Mono.CSharp {
                                OptAttributes.Emit ();
                }
 
-               public override bool DefineMembers ()
-               {
-                       return true;
-               }
-
                public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
                                                        MemberFilter filter, object criteria)
                {
@@ -1990,85 +1817,10 @@ namespace Mono.CSharp {
                }
        }
 
-       public class NullableType : TypeExpr
-       {
-               Expression underlying;
-
-               public NullableType (Expression underlying, Location l)
-               {
-                       this.underlying = underlying;
-                       loc = l;
-
-                       eclass = ExprClass.Type;
-               }
-
-               public NullableType (Type type, Location loc)
-                       : this (new TypeExpression (type, loc), loc)
-               { }
-
-               public override string Name {
-                       get { return underlying.ToString () + "?"; }
-               }
-
-               public override string FullName {
-                       get { return underlying.ToString () + "?"; }
-               }
-
-               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
-               {
-                       TypeArguments args = new TypeArguments (loc);
-                       args.Add (underlying);
-
-                       ConstructedType ctype = new ConstructedType (TypeManager.generic_nullable_type, args, loc);
-                       return ctype.ResolveAsTypeTerminal (ec, false);
-               }
-       }
-
        public partial class TypeManager
        {
-               //
-               // A list of core types that the compiler requires or uses
-               //
                static public Type activator_type;
-               static public Type generic_ilist_type;
-               static public Type generic_icollection_type;
-               static public Type generic_ienumerator_type;
-               static public Type generic_ienumerable_type;
-               static public Type generic_nullable_type;
-
-               //
-               // These methods are called by code generated by the compiler
-               //
-               static public MethodInfo activator_create_instance;
-
-               static void InitGenericCoreTypes ()
-               {
-                       activator_type = CoreLookupType ("System", "Activator");
-
-                       generic_ilist_type = CoreLookupType (
-                               "System.Collections.Generic", "IList", 1);
-                       generic_icollection_type = CoreLookupType (
-                               "System.Collections.Generic", "ICollection", 1);
-                       generic_ienumerator_type = CoreLookupType (
-                               "System.Collections.Generic", "IEnumerator", 1);
-                       generic_ienumerable_type = CoreLookupType (
-                               "System.Collections.Generic", "IEnumerable", 1);
-                       generic_nullable_type = CoreLookupType (
-                               "System", "Nullable", 1);
-               }
-
-               static void InitGenericCodeHelpers ()
-               {
-                       // Activator
-                       activator_create_instance = GetMethod (
-                               activator_type, "CreateInstance", Type.EmptyTypes);
-               }
-
-               static Type CoreLookupType (string ns, string name, int arity)
-               {
-                       return CoreLookupType (ns, MemberName.MakeName (name, arity));
-               }
-
+       
                public static TypeContainer LookupGenericTypeContainer (Type t)
                {
                        t = DropGenericTypeArguments (t);
@@ -2088,7 +1840,7 @@ namespace Mono.CSharp {
                                // become equal.
                                //
                                while (b.IsArray) {
-                                       b = b.GetElementType ();
+                                       b = GetElementType (b);
                                        if (a.Equals (b))
                                                return false;
                                }
@@ -2156,8 +1908,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);
                        }
@@ -2226,7 +1978,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Type inference.
                /// </summary>
-               public static bool InferTypeArguments (ParameterData apd,
+               public static bool InferTypeArguments (AParametersCollection apd,
                                                       ref MethodBase method)
                {
                        if (!TypeManager.IsGenericMethod (method))
@@ -2284,7 +2036,7 @@ namespace Mono.CSharp {
 
                public override Type[] InferDelegateArguments (MethodBase method)
                {
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        if (arg_count != pd.Count)
                                return null;
 
@@ -2295,7 +2047,7 @@ namespace Mono.CSharp {
                        Type[] arg_types = (Type[])arguments.ToArray (typeof (Type));
 
                        for (int i = 0; i < arg_count; i++) {
-                               param_types[i] = pd.ParameterType (i);
+                               param_types[i] = pd.Types [i];
                        }
 
                        if (!InferTypeArguments (param_types, arg_types, inferred_types))
@@ -2306,7 +2058,7 @@ namespace Mono.CSharp {
 
                public override Type[] InferMethodArguments (EmitContext ec, MethodBase method)
                {
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        Type[] method_generic_args = method.GetGenericArguments ();
                        Type [] inferred_types = new Type [method_generic_args.Length];
                        Type[] arg_types = new Type [pd.Count];
@@ -2320,12 +2072,12 @@ namespace Mono.CSharp {
                                if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
                                        continue;
 
-                               if (!TypeInferenceV2.UnifyType (pd.ParameterType (i), a.Type, inferred_types))
+                               if (!TypeInferenceV2.UnifyType (pd.Types [i], a.Type, inferred_types))
                                        return null;
                        }
 
                        if (pd.HasParams) {
-                               Type element_type = TypeManager.GetElementType (pd.ParameterType (a_count));
+                               Type element_type = TypeManager.GetElementType (pd.Types [a_count]);
                                for (int i = a_count; i < arg_count; i++) {
                                        Argument a = (Argument) arguments [i];
                                        if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
@@ -2387,7 +2139,7 @@ namespace Mono.CSharp {
                                        if (at.GetArrayRank () != pt.GetArrayRank ())
                                                return false;
 
-                                       return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
+                                       return UnifyType (TypeManager.GetElementType (pt), TypeManager.GetElementType (at), inferred);
                                }
 
                                if (!pt.IsGenericType)
@@ -2467,7 +2219,7 @@ namespace Mono.CSharp {
 
                public override Type[] InferDelegateArguments (MethodBase method)
                {
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        if (arg_count != pd.Count)
                                return null;
 
@@ -2497,7 +2249,7 @@ namespace Mono.CSharp {
                        if (!context.UnfixedVariableExists)
                                return Type.EmptyTypes;
 
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        if (!InferInPhases (ec, context, pd))
                                return null;
 
@@ -2507,7 +2259,7 @@ namespace Mono.CSharp {
                //
                // Implements method type arguments inference
                //
-               bool InferInPhases (EmitContext ec, TypeInferenceContext tic, ParameterData methodParameters)
+               bool InferInPhases (EmitContext ec, TypeInferenceContext tic, AParametersCollection methodParameters)
                {
                        int params_arguments_start;
                        if (methodParameters.HasParams) {
@@ -2515,6 +2267,8 @@ namespace Mono.CSharp {
                        } else {
                                params_arguments_start = arg_count;
                        }
+
+                       Type [] ptypes = methodParameters.Types;
                        
                        //
                        // The first inference phase
@@ -2530,6 +2284,9 @@ namespace Mono.CSharp {
                                                method_parameter = methodParameters.Types [params_arguments_start];
                                        else
                                                method_parameter = TypeManager.GetElementType (methodParameters.Types [params_arguments_start]);
+
+                                       ptypes = (Type[]) ptypes.Clone ();
+                                       ptypes [i] = method_parameter;
                                }
 
                                //
@@ -2543,7 +2300,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               if (a.Expr.Type == TypeManager.null_type)
+                               if (a.Expr is NullLiteral)
                                        continue;
 
                                //
@@ -2557,16 +2314,16 @@ namespace Mono.CSharp {
                        // we don't need to call it in cycle
                        //
                        bool fixed_any = false;
-                       if (!tic.FixIndependentTypeArguments (methodParameters, ref fixed_any))
+                       if (!tic.FixIndependentTypeArguments (ptypes, ref fixed_any))
                                return false;
 
-                       return DoSecondPhase (ec, tic, methodParameters, !fixed_any);
+                       return DoSecondPhase (ec, tic, ptypes, !fixed_any);
                }
 
-               bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, ParameterData methodParameters, bool fixDependent)
+               bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, Type[] methodParameters, bool fixDependent)
                {
                        bool fixed_any = false;
-                       if (fixDependent && !tic.FixDependentTypes (methodParameters, ref fixed_any))
+                       if (fixDependent && !tic.FixDependentTypes (ref fixed_any))
                                return false;
 
                        // If no further unfixed type variables exist, type inference succeeds
@@ -2580,7 +2337,10 @@ namespace Mono.CSharp {
                        // contain unfixed type variables but the input types do not,
                        // an output type inference is made
                        for (int i = 0; i < arg_count; i++) {
-                               Type t_i = methodParameters.ParameterType (i);
+                               
+                               // Align params arguments
+                               Type t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i];
+                               
                                if (!TypeManager.IsDelegateType (t_i)) {
                                        if (TypeManager.DropGenericTypeArguments (t_i) != TypeManager.expression_type)
                                                continue;
@@ -2611,6 +2371,7 @@ namespace Mono.CSharp {
                readonly Type[] unfixed_types;
                readonly Type[] fixed_types;
                readonly ArrayList[] bounds;
+               bool failed;
                
                public TypeInferenceContext (Type[] typeArguments)
                {
@@ -2639,6 +2400,12 @@ namespace Mono.CSharp {
 
                void AddToBounds (Type t, int index)
                {
+                       //
+                       // Some types cannot be used as type arguments
+                       //
+                       if (t == TypeManager.void_type || t.IsPointer)
+                               return;
+
                        ArrayList a = bounds [index];
                        if (a == null) {
                                a = new ArrayList ();
@@ -2651,13 +2418,13 @@ namespace Mono.CSharp {
                        //
                        // SPEC: does not cover type inference using constraints
                        //
-                       if (TypeManager.IsGenericParameter (t)) {
-                               GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
-                               if (constraints != null) {
-                                       //if (constraints.EffectiveBaseClass != null)
-                                       //      t = constraints.EffectiveBaseClass;
-                               }
-                       }
+                       //if (TypeManager.IsGenericParameter (t)) {
+                       //    GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
+                       //    if (constraints != null) {
+                       //        //if (constraints.EffectiveBaseClass != null)
+                       //        //    t = constraints.EffectiveBaseClass;
+                       //    }
+                       //}
                        a.Add (t);
                }
                
@@ -2733,7 +2500,7 @@ namespace Mono.CSharp {
                // a, There is at least one type variable Xj that depends on Xi
                // b, Xi has a non-empty set of bounds
                // 
-               public bool FixDependentTypes (ParameterData methodParameters, ref bool fixed_any)
+               public bool FixDependentTypes (ref bool fixed_any)
                {
                        for (int i = 0; i < unfixed_types.Length; ++i) {
                                if (unfixed_types[i] == null)
@@ -2754,11 +2521,11 @@ namespace Mono.CSharp {
                //
                // All unfixed type variables Xi which depend on no Xj are fixed
                //
-               public bool FixIndependentTypeArguments (ParameterData methodParameters, ref bool fixed_any)
+               public bool FixIndependentTypeArguments (Type[] methodParameters, ref bool fixed_any)
                {
                        ArrayList types_to_fix = new ArrayList (unfixed_types);
-                       for (int i = 0; i < methodParameters.Types.Length; ++i) {
-                               Type t = methodParameters.Types [i];
+                       for (int i = 0; i < methodParameters.Length; ++i) {
+                               Type t = methodParameters[i];
                                if (t.IsGenericParameter)
                                        continue;
 
@@ -2808,6 +2575,9 @@ namespace Mono.CSharp {
                        if (unfixed_types[i] == null)
                                throw new InternalErrorException ("Type argument has been already fixed");
 
+                       if (failed)
+                               return false;
+
                        ArrayList candidates = (ArrayList)bounds [i];
                        if (candidates == null)
                                return false;
@@ -2860,8 +2630,15 @@ namespace Mono.CSharp {
                //
                public Type InflateGenericArgument (Type parameter)
                {
-                       if (parameter.IsGenericParameter)
+                       if (parameter.IsGenericParameter) {
+                               //
+                               // Inflate method generic argument (MVAR) only
+                               //
+                               if (parameter.DeclaringMethod == null)
+                                       return parameter;
+
                                return fixed_types [parameter.GenericParameterPosition];
+                       }
 
                        if (parameter.IsGenericType) {
                                Type [] parameter_targs = parameter.GetGenericArguments ();
@@ -2899,7 +2676,7 @@ namespace Mono.CSharp {
                        }
 
                        // All generic input arguments have to be fixed
-                       ParameterData d_parameters = TypeManager.GetParameterData (invoke);
+                       AParametersCollection d_parameters = TypeManager.GetParameterData (invoke);
                        return AllTypesAreFixed (d_parameters.Types);
                }
                
@@ -2927,10 +2704,6 @@ namespace Mono.CSharp {
                //
                public int LowerBoundInference (Type u, Type v)
                {
-                       // Remove ref, out modifiers
-                       if (v.IsByRef)
-                               v = v.GetElementType ();
-                       
                        // If V is one of the unfixed type arguments
                        int pos = IsUnfixed (v);
                        if (pos != -1) {
@@ -2994,7 +2767,8 @@ namespace Mono.CSharp {
                                u_candidates.AddRange (TypeManager.GetInterfaces (u));
 
                                Type open_v = v.GetGenericTypeDefinition ();
-                               int score = 0;
+                               Type [] unique_candidate_targs = null;
+                               Type [] ga_v = v.GetGenericArguments ();                        
                                foreach (Type u_candidate in u_candidates) {
                                        if (!u_candidate.IsGenericType || u_candidate.IsGenericTypeDefinition)
                                                continue;
@@ -3002,17 +2776,35 @@ namespace Mono.CSharp {
                                        if (TypeManager.DropGenericTypeArguments (u_candidate) != open_v)
                                                continue;
 
-                                       Type [] ga_u = u_candidate.GetGenericArguments ();
-                                       Type [] ga_v = v.GetGenericArguments ();
-                                       bool all_exact = true;
-                                       for (int i = 0; i < ga_u.Length; ++i)
-                                               if (ExactInference (ga_u [i], ga_v [i]) == 0)
-                                                       all_exact = false;
+                                       //
+                                       // The unique set of types U1..Uk means that if we have an interface C<T>,
+                                       // class U: C<int>, C<long> then no type inference is made when inferring
+                                       // from U to C<T> because T could be int or long
+                                       //
+                                       if (unique_candidate_targs != null) {
+                                               Type[] second_unique_candidate_targs = u_candidate.GetGenericArguments ();
+                                               if (TypeManager.IsEqual (unique_candidate_targs, second_unique_candidate_targs)) {
+                                                       unique_candidate_targs = second_unique_candidate_targs;
+                                                       continue;
+                                               }
+                                               
+                                               //
+                                               // This should always cause type inference failure
+                                               //
+                                               failed = true;
+                                               return 1;
+                                       }
 
-                                       if (all_exact && score == 0)
-                                               ++score;
+                                       unique_candidate_targs = u_candidate.GetGenericArguments ();
+                               }
+
+                               if (unique_candidate_targs != null) {
+                                       int score = 0;
+                                       for (int i = 0; i < unique_candidate_targs.Length; ++i)
+                                               if (ExactInference (unique_candidate_targs [i], ga_v [i]) == 0)
+                                                       ++score;
+                                       return score;
                                }
-                               return score;
                        }
 
                        return 0;
@@ -3030,7 +2822,7 @@ namespace Mono.CSharp {
                                MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
 
                                if (rt == null) {
-                                       ParameterData pd = TypeManager.GetParameterData (invoke);
+                                       AParametersCollection pd = TypeManager.GetParameterData (invoke);
                                        return ame.Parameters.Count == pd.Count ? 1 : 0;
                                }
 
@@ -3043,16 +2835,37 @@ namespace Mono.CSharp {
                                return LowerBoundInference (rt, rtype) + 1;
                        }
 
+                       //
+                       // if E is a method group and T is a delegate type or expression tree type
+                       // return type Tb with parameter types T1..Tk and return type Tb, and overload
+                       // resolution of E with the types T1..Tk yields a single method with return type U,
+                       // then a lower-bound inference is made from U for Tb.
+                       //
                        if (e is MethodGroupExpr) {
+                               // TODO: Or expression tree
                                if (!TypeManager.IsDelegateType (t))
                                        return 0;
 
                                MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
                                Type rtype = invoke.ReturnType;
+#if MS_COMPATIBLE
+                               // Blablabla, because reflection does not work with dynamic types
+                               Type [] g_args = t.GetGenericArguments ();
+                               rtype = g_args [rtype.GenericParameterPosition];
+#endif
+
                                if (!TypeManager.IsGenericType (rtype))
                                        return 0;
-                               
+
+                               MethodGroupExpr mg = (MethodGroupExpr) e;
+                               ArrayList args = DelegateCreation.CreateDelegateMethodArguments (invoke, e.Location);
+                               mg = mg.OverloadResolve (ec, ref args, true, e.Location);
+                               if (mg == null)
+                                       return 0;
+
+                               // TODO: What should happen when return type is of generic type ?
                                throw new NotImplementedException ();
+//                             return LowerBoundInference (null, rtype) + 1;
                        }
 
                        //
@@ -3062,10 +2875,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;
                        }
 
@@ -3088,887 +2902,4 @@ namespace Mono.CSharp {
                        }
                }
        }
-
-       public abstract class Nullable
-       {
-               public sealed class NullableInfo
-               {
-                       public readonly Type Type;
-                       public readonly Type UnderlyingType;
-                       public readonly MethodInfo HasValue;
-                       public readonly MethodInfo Value;
-                       public readonly ConstructorInfo Constructor;
-
-                       public NullableInfo (Type type)
-                       {
-                               Type = type;
-                               UnderlyingType = TypeManager.GetTypeArguments (type) [0];
-
-                               PropertyInfo has_value_pi = TypeManager.GetProperty (type, "HasValue");
-                               PropertyInfo value_pi = TypeManager.GetProperty (type, "Value");
-
-                               HasValue = has_value_pi.GetGetMethod (false);
-                               Value = value_pi.GetGetMethod (false);
-                               Constructor = type.GetConstructor (new Type[] { UnderlyingType });
-                       }
-               }
-               
-               public class HasValue : Expression
-               {
-                       Expression expr;
-                       NullableInfo info;
-
-                       private HasValue (Expression expr)
-                       {
-                               this.expr = expr;
-                       }
-                       
-                       public static Expression Create (Expression expr, EmitContext ec)
-                       {
-                               return new HasValue (expr).Resolve (ec);
-                       }
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               IMemoryLocation memory_loc = expr as IMemoryLocation;
-                               if (memory_loc == null) {
-                                       LocalTemporary temp = new LocalTemporary (expr.Type);
-                                       expr.Emit (ec);
-                                       temp.Store (ec);
-                                       memory_loc = temp;
-                               }
-                               memory_loc.AddressOf (ec, AddressOp.LoadStore);
-                               ec.ig.EmitCall (OpCodes.Call, info.HasValue, null);
-                       }
-
-                       public override Expression DoResolve (EmitContext ec)
-                       {
-                               this.info = new NullableInfo (expr.Type);
-
-                               type = TypeManager.bool_type;
-                               eclass = expr.eclass;
-                               return this;
-                       }
-               }               
-
-               public class Unwrap : Expression, IMemoryLocation, IAssignMethod
-               {
-                       Expression expr;
-                       NullableInfo info;
-
-                       LocalTemporary temp;
-                       bool has_temp;
-
-                       protected Unwrap (Expression expr)
-                       {
-                               this.expr = expr;
-                               this.loc = expr.Location;
-                       }
-
-                       public static Unwrap Create (Expression expr, EmitContext ec)
-                       {
-                               return new Unwrap (expr).Resolve (ec) as Unwrap;
-                       }
-                       
-                       public override Expression CreateExpressionTree (EmitContext ec)
-                       {
-                               return expr.CreateExpressionTree (ec);
-                       }                       
-
-                       public override Expression DoResolve (EmitContext ec)
-                       {
-                               if (expr == null)
-                                       return null;
-
-                               temp = new LocalTemporary (expr.Type);
-
-                               info = new NullableInfo (expr.Type);
-                               type = info.UnderlyingType;
-                               eclass = expr.eclass;
-                               return this;
-                       }
-                       
-                       public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
-                       {
-                               return DoResolve (ec);
-                       }                       
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               AddressOf (ec, AddressOp.LoadStore);
-                               ec.ig.EmitCall (OpCodes.Call, info.Value, null);
-                       }
-
-                       public void EmitCheck (EmitContext ec)
-                       {
-                               AddressOf (ec, AddressOp.LoadStore);
-                               ec.ig.EmitCall (OpCodes.Call, info.HasValue, null);
-                       }
-
-                       public override bool IsNull {
-                               get {
-                                       return expr.IsNull;
-                               }
-                       }
-
-                       public void Store (EmitContext ec)
-                       {
-                               create_temp (ec);
-                       }
-
-                       void create_temp (EmitContext ec)
-                       {
-                               if ((temp != null) && !has_temp) {
-                                       expr.Emit (ec);
-                                       temp.Store (ec);
-                                       has_temp = true;
-                               }
-                       }
-
-                       public void AddressOf (EmitContext ec, AddressOp mode)
-                       {
-                               create_temp (ec);
-                               if (temp != null)
-                                       temp.AddressOf (ec, AddressOp.LoadStore);
-                               else
-                                       ((IMemoryLocation) expr).AddressOf (ec, AddressOp.LoadStore);
-                       }
-
-                       public void Emit (EmitContext ec, bool leave_copy)
-                       {
-                               create_temp (ec);
-                               if (leave_copy) {
-                                       if (temp != null)
-                                               temp.Emit (ec);
-                                       else
-                                               expr.Emit (ec);
-                               }
-
-                               Emit (ec);
-                       }
-
-                       public void EmitAssign (EmitContext ec, Expression source,
-                                               bool leave_copy, bool prepare_for_load)
-                       {
-                               InternalWrap wrap = new InternalWrap (source, info, loc);
-                               ((IAssignMethod) expr).EmitAssign (ec, wrap, leave_copy, false);
-                       }
-
-                       protected class InternalWrap : Expression
-                       {
-                               public Expression expr;
-                               public NullableInfo info;
-
-                               public InternalWrap (Expression expr, NullableInfo info, Location loc)
-                               {
-                                       this.expr = expr;
-                                       this.info = info;
-                                       this.loc = loc;
-
-                                       type = info.Type;
-                                       eclass = ExprClass.Value;
-                               }
-
-                               public override Expression DoResolve (EmitContext ec)
-                               {
-                                       return this;
-                               }
-
-                               public override void Emit (EmitContext ec)
-                               {
-                                       expr.Emit (ec);
-                                       ec.ig.Emit (OpCodes.Newobj, info.Constructor);
-                               }
-                       }
-               }
-
-               public class Wrap : Expression
-               {
-                       Expression expr;
-                       NullableInfo info;
-
-                       protected Wrap (Expression expr)
-                       {
-                               this.expr = expr;
-                               this.loc = expr.Location;
-                       }
-
-                       public static Wrap Create (Expression expr, EmitContext ec)
-                       {
-                               return new Wrap (expr).Resolve (ec) as Wrap;
-                       }
-                       
-                       public override Expression CreateExpressionTree (EmitContext ec)
-                       {
-                               ArrayList args = new ArrayList (2);
-                               args.Add (new Argument (expr.CreateExpressionTree (ec)));
-                               args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
-                               return CreateExpressionFactoryCall ("Convert", args);
-                       }                       
-
-                       public override Expression DoResolve (EmitContext ec)
-                       {
-                               if (expr == null)
-                                       return null;
-
-                               TypeExpr target_type = new NullableType (expr.Type, loc);
-                               target_type = target_type.ResolveAsTypeTerminal (ec, false);
-                               if (target_type == null)
-                                       return null;
-
-                               type = target_type.Type;
-                               info = new NullableInfo (type);
-                               eclass = ExprClass.Value;
-                               return this;
-                       }
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               expr.Emit (ec);
-                               ec.ig.Emit (OpCodes.Newobj, info.Constructor);
-                       }
-               }
-
-               //
-               // Represents null value converted to nullable type
-               //
-               public class Null : Expression, IMemoryLocation
-               {
-                       public Null (Type target_type, Location loc)
-                       {
-                               this.type = target_type;
-                               this.loc = loc;
-
-                               eclass = ExprClass.Value;
-                       }
-                       
-                       public override Expression CreateExpressionTree (EmitContext ec)
-                       {
-                               return EmptyCast.Create (new NullConstant (loc), type).CreateExpressionTree (ec);
-                       }                       
-               
-                       public override Expression DoResolve (EmitContext ec)
-                       {
-                               return this;
-                       }
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               LocalTemporary value_target = new LocalTemporary (type);
-
-                               value_target.AddressOf (ec, AddressOp.Store);
-                               ec.ig.Emit (OpCodes.Initobj, type);
-                               value_target.Emit (ec);
-                       }
-                       
-                       public override bool IsNull {
-                               get {
-                                       return true;
-                               }
-                       }                       
-
-                       public void AddressOf (EmitContext ec, AddressOp Mode)
-                       {
-                               LocalTemporary value_target = new LocalTemporary (type);
-                                       
-                               value_target.AddressOf (ec, AddressOp.Store);
-                               ec.ig.Emit (OpCodes.Initobj, type);
-                               ((IMemoryLocation) value_target).AddressOf (ec, Mode);
-                       }
-               }
-
-               public abstract class Lifted : Expression, IMemoryLocation
-               {
-                       Expression expr, underlying, wrap, null_value;
-                       Unwrap unwrap;
-
-                       protected Lifted (Expression expr, Location loc)
-                       {
-                               this.expr = expr;
-                               this.loc = loc;
-                       }
-                       
-                       public override Expression CreateExpressionTree (EmitContext ec)
-                       {
-                               return expr.CreateExpressionTree (ec);
-                       }                       
-
-                       public override Expression DoResolve (EmitContext ec)
-                       {
-                               expr = expr.Resolve (ec);
-                               if (expr == null)
-                                       return null;
-
-                               unwrap = Unwrap.Create (expr, ec);
-                               if (unwrap == null)
-                                       return null;
-
-                               underlying = ResolveUnderlying (unwrap, ec);
-                               if (underlying == null)
-                                       return null;
-
-                               wrap = Wrap.Create (underlying, ec);
-                               if (wrap == null)
-                                       return null;
-
-                               null_value = new Null (wrap.Type, loc).Resolve (ec);
-                               if (null_value == null)
-                                       return null;
-
-                               type = wrap.Type;
-                               eclass = ExprClass.Value;
-                               return this;
-                       }
-
-                       protected abstract Expression ResolveUnderlying (Expression unwrap, EmitContext ec);
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               ILGenerator ig = ec.ig;
-                               Label is_null_label = ig.DefineLabel ();
-                               Label end_label = ig.DefineLabel ();
-
-                               unwrap.EmitCheck (ec);
-                               ig.Emit (OpCodes.Brfalse, is_null_label);
-
-                               wrap.Emit (ec);
-                               ig.Emit (OpCodes.Br, end_label);
-
-                               ig.MarkLabel (is_null_label);
-                               null_value.Emit (ec);
-
-                               ig.MarkLabel (end_label);
-                       }
-
-                       public void AddressOf (EmitContext ec, AddressOp mode)
-                       {
-                               unwrap.AddressOf (ec, mode);
-                       }
-               }
-
-               public class LiftedConversion : Lifted
-               {
-                       public readonly bool IsUser;
-                       public readonly bool IsExplicit;
-                       public readonly Type TargetType;
-
-                       public LiftedConversion (Expression expr, Type target_type, bool is_user,
-                                                bool is_explicit, Location loc)
-                               : base (expr, loc)
-                       {
-                               this.IsUser = is_user;
-                               this.IsExplicit = is_explicit;
-                               this.TargetType = target_type;
-                       }
-
-                       protected override Expression ResolveUnderlying (Expression unwrap, EmitContext ec)
-                       {
-                               Type type = TypeManager.GetTypeArguments (TargetType) [0];
-
-                               if (IsUser) {
-                                       return Convert.UserDefinedConversion (ec, unwrap, type, loc, IsExplicit);
-                               } else {
-                                       if (IsExplicit)
-                                               return Convert.ExplicitConversion (ec, unwrap, type, loc);
-                                       else
-                                               return Convert.ImplicitConversion (ec, unwrap, type, loc);
-                               }
-                       }
-               }
-
-               public class LiftedUnaryOperator : Lifted
-               {
-                       public readonly Unary.Operator Oper;
-
-                       public LiftedUnaryOperator (Unary.Operator op, Expression expr, Location loc)
-                               : base (expr, loc)
-                       {
-                               this.Oper = op;
-                       }
-
-                       protected override Expression ResolveUnderlying (Expression unwrap, EmitContext ec)
-                       {
-                               return new Unary (Oper, unwrap, loc).Resolve (ec);
-                       }
-               }
-
-               public class LiftedBinaryOperator : Binary
-               {
-                       Expression underlying, null_value, bool_wrap;
-                       Unwrap left_unwrap, right_unwrap;
-                       bool is_equality, is_comparision, is_boolean;
-
-                       public LiftedBinaryOperator (Binary.Operator op, Expression left, Expression right,
-                                                    Location loc)
-                               : base (op, left, right)
-                       {
-                               this.loc = loc;
-                       }
-
-                       public override Expression DoResolve (EmitContext ec)
-                       {
-                               if ((Oper == Binary.Operator.LogicalAnd) ||
-                                   (Oper == Binary.Operator.LogicalOr)) {
-                                       Error_OperatorCannotBeApplied ();
-                                       return null;
-                               }
-
-                               //
-                               // Optimize null comparisons
-                               //
-                               if (Oper == Binary.Operator.Equality) {
-                                       if (left.IsNull)
-                                               return new Unary (Unary.Operator.LogicalNot, Nullable.HasValue.Create (right, ec), loc).Resolve (ec);
-                                       if (right.IsNull)
-                                               return new Unary (Unary.Operator.LogicalNot, Nullable.HasValue.Create (left, ec), loc).Resolve (ec);
-                               }
-                               if (Oper == Binary.Operator.Inequality) {
-                                       if (left.IsNull)
-                                               return Nullable.HasValue.Create (right, ec);
-                                       if (right.IsNull)
-                                               return Nullable.HasValue.Create (left, ec);
-                               }
-                               
-                               if (TypeManager.IsNullableType (left.Type)) {
-                                       left = left_unwrap = Unwrap.Create (left, ec);
-                                       if (left == null)
-                                               return null;
-                               }
-
-                               if (TypeManager.IsNullableType (right.Type)) {
-                                       right = right_unwrap = Unwrap.Create (right, ec);
-                                       if (right == null)
-                                               return null;
-                               }
-
-                               if (((Oper == Binary.Operator.BitwiseAnd) || (Oper == Binary.Operator.BitwiseOr)) &&
-                                   ((left.Type == TypeManager.bool_type) && (right.Type == TypeManager.bool_type))) {
-                                       Expression empty = new EmptyExpression (TypeManager.bool_type);
-                                       bool_wrap = Wrap.Create (empty, ec);
-                                       null_value = new Null (bool_wrap.Type, loc).Resolve (ec);
-
-                                       type = bool_wrap.Type;
-                                       is_boolean = true;
-                               } else if ((Oper == Binary.Operator.Equality) || (Oper == Binary.Operator.Inequality)) {
-                                       underlying = new Binary (Oper, left, right).Resolve (ec);
-                                       if (underlying == null)
-                                               return null;
-                                       type = TypeManager.bool_type;
-                                       is_equality = true;
-                               } else if ((Oper == Binary.Operator.LessThan) ||
-                                          (Oper == Binary.Operator.GreaterThan) ||
-                                          (Oper == Binary.Operator.LessThanOrEqual) ||
-                                          (Oper == Binary.Operator.GreaterThanOrEqual)) {
-                                       underlying = new Binary (Oper, left, right).Resolve (ec);
-                                       if (underlying == null)
-                                               return null;
-
-                                       type = TypeManager.bool_type;
-                                       is_comparision = true;
-                               } else {
-                                       underlying = new Binary (Oper, left, right).Resolve (ec);
-                                       if (underlying == null)
-                                               return null;
-
-                                       underlying = Wrap.Create (underlying, ec);
-                                       if (underlying == null)
-                                               return null;
-
-                                       type = underlying.Type;
-                                       null_value = new Null (type, loc).Resolve (ec);
-                               }
-
-                               eclass = ExprClass.Value;
-                               return this;
-                       }
-
-                       void EmitBoolean (EmitContext ec)
-                       {
-                               ILGenerator ig = ec.ig;
-
-                               Label left_is_null_label = ig.DefineLabel ();
-                               Label right_is_null_label = ig.DefineLabel ();
-                               Label is_null_label = ig.DefineLabel ();
-                               Label wrap_label = ig.DefineLabel ();
-                               Label end_label = ig.DefineLabel ();
-
-                               if (left_unwrap != null) {
-                                       left_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brfalse, left_is_null_label);
-                               }
-
-                               left.Emit (ec);
-                               ig.Emit (OpCodes.Dup);
-                               if ((Oper == Binary.Operator.BitwiseOr) || (Oper == Binary.Operator.LogicalOr))
-                                       ig.Emit (OpCodes.Brtrue, wrap_label);
-                               else
-                                       ig.Emit (OpCodes.Brfalse, wrap_label);
-
-                               if (right_unwrap != null) {
-                                       right_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brfalse, right_is_null_label);
-                               }
-
-                               if ((Oper == Binary.Operator.LogicalAnd) || (Oper == Binary.Operator.LogicalOr))
-                                       ig.Emit (OpCodes.Pop);
-
-                               right.Emit (ec);
-                               if (Oper == Binary.Operator.BitwiseOr)
-                                       ig.Emit (OpCodes.Or);
-                               else if (Oper == Binary.Operator.BitwiseAnd)
-                                       ig.Emit (OpCodes.And);
-                               ig.Emit (OpCodes.Br, wrap_label);
-
-                               ig.MarkLabel (left_is_null_label);
-                               if (right_unwrap != null) {
-                                       right_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brfalse, is_null_label);
-                               }
-
-                               right.Emit (ec);
-                               ig.Emit (OpCodes.Dup);
-                               if ((Oper == Binary.Operator.BitwiseOr) || (Oper == Binary.Operator.LogicalOr))
-                                       ig.Emit (OpCodes.Brtrue, wrap_label);
-                               else
-                                       ig.Emit (OpCodes.Brfalse, wrap_label);
-
-                               ig.MarkLabel (right_is_null_label);
-                               ig.Emit (OpCodes.Pop);
-                               ig.MarkLabel (is_null_label);
-                               null_value.Emit (ec);
-                               ig.Emit (OpCodes.Br, end_label);
-
-                               ig.MarkLabel (wrap_label);
-                               ig.Emit (OpCodes.Nop);
-                               bool_wrap.Emit (ec);
-                               ig.Emit (OpCodes.Nop);
-
-                               ig.MarkLabel (end_label);
-                       }
-
-                       void EmitEquality (EmitContext ec)
-                       {
-                               if (left.IsNull || right.IsNull)
-                                       throw new InternalErrorException ("Unoptimized nullable comparison");
-
-                               ILGenerator ig = ec.ig;
-
-                               Label both_have_value_label = ig.DefineLabel ();
-                               Label end_label = ig.DefineLabel ();
-
-                               if (left_unwrap != null && right_unwrap != null) {
-                                       Label dissimilar_label = ig.DefineLabel ();
-
-                                       left_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Dup);
-                                       right_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Bne_Un, dissimilar_label);
-
-                                       ig.Emit (OpCodes.Brtrue, both_have_value_label);
-
-                                       // both are null
-                                       if (Oper == Binary.Operator.Equality)
-                                               ig.Emit (OpCodes.Ldc_I4_1);
-                                       else
-                                               ig.Emit (OpCodes.Ldc_I4_0);
-                                       ig.Emit (OpCodes.Br, end_label);
-
-                                       ig.MarkLabel (dissimilar_label);
-                                       ig.Emit (OpCodes.Pop);
-                               } else if (left_unwrap != null) {
-                                       left_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brtrue, both_have_value_label);
-                               } else if (right_unwrap != null) {
-                                       right_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brtrue, both_have_value_label);
-                               } else {
-                                       throw new InternalErrorException ("shouldn't get here");
-                               }
-
-                               // one is null while the other isn't
-                               if (Oper == Binary.Operator.Equality)
-                                       ig.Emit (OpCodes.Ldc_I4_0);
-                               else
-                                       ig.Emit (OpCodes.Ldc_I4_1);
-                               ig.Emit (OpCodes.Br, end_label);
-
-                               ig.MarkLabel (both_have_value_label);
-                               underlying.Emit (ec);
-
-                               ig.MarkLabel (end_label);
-                       }
-
-                       void EmitComparision (EmitContext ec)
-                       {
-                               ILGenerator ig = ec.ig;
-
-                               Label is_null_label = ig.DefineLabel ();
-                               Label end_label = ig.DefineLabel ();
-
-                               if (left_unwrap != null) {
-                                       left_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brfalse, is_null_label);
-                               }
-
-                               if (right_unwrap != null) {
-                                       right_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brfalse, is_null_label);
-                               }
-
-                               underlying.Emit (ec);
-                               ig.Emit (OpCodes.Br, end_label);
-
-                               ig.MarkLabel (is_null_label);
-                               ig.Emit (OpCodes.Ldc_I4_0);
-
-                               ig.MarkLabel (end_label);
-                       }
-                       
-                       public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
-                       {
-                               Emit (ec);
-                               ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
-                       }                       
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               if (left_unwrap != null)
-                                       left_unwrap.Store (ec);
-                               if (right_unwrap != null)
-                                       right_unwrap.Store (ec);
-
-                               if (is_boolean) {
-                                       EmitBoolean (ec);
-                                       return;
-                               } else if (is_equality) {
-                                       EmitEquality (ec);
-                                       return;
-                               } else if (is_comparision) {
-                                       EmitComparision (ec);
-                                       return;
-                               }
-
-                               ILGenerator ig = ec.ig;
-
-                               Label is_null_label = ig.DefineLabel ();
-                               Label end_label = ig.DefineLabel ();
-
-                               if (left_unwrap != null) {
-                                       left_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brfalse, is_null_label);
-                               }
-
-                               if (right_unwrap != null) {
-                                       right_unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brfalse, is_null_label);
-                               }
-
-                               underlying.Emit (ec);
-                               ig.Emit (OpCodes.Br, end_label);
-
-                               ig.MarkLabel (is_null_label);
-                               null_value.Emit (ec);
-
-                               ig.MarkLabel (end_label);
-                       }
-               }
-
-               public class NullCoalescingOperator : Expression
-               {
-                       Expression left, right;
-                       Unwrap unwrap;
-
-                       public NullCoalescingOperator (Expression left, Expression right, Location loc)
-                       {
-                               this.left = left;
-                               this.right = right;
-                               this.loc = loc;
-                       }
-                       
-                       public override Expression CreateExpressionTree (EmitContext ec)
-                       {
-                               UserCast uc = left as UserCast;
-                               Expression conversion = null;
-                               if (uc != null) {
-                                       left = uc.Source;
-
-                                       ArrayList c_args = new ArrayList (2);
-                                       c_args.Add (new Argument (uc.CreateExpressionTree (ec)));
-                                       c_args.Add (new Argument (left.CreateExpressionTree (ec)));
-                                       conversion = CreateExpressionFactoryCall ("Lambda", c_args);
-                               }
-
-                               ArrayList args = new ArrayList (3);
-                               args.Add (new Argument (left.CreateExpressionTree (ec)));
-                               args.Add (new Argument (right.CreateExpressionTree (ec)));
-                               if (conversion != null)
-                                       args.Add (new Argument (conversion));
-                               
-                               return CreateExpressionFactoryCall ("Coalesce", args);
-                       }                       
-
-                       public override Expression DoResolve (EmitContext ec)
-                       {
-                               if (type != null)
-                                       return this;
-
-                               left = left.Resolve (ec);
-                               right = right.Resolve (ec);
-
-                               if (left == null || right == null)
-                                       return null;
-
-                               eclass = ExprClass.Value;
-                               Type ltype = left.Type, rtype = right.Type;
-                               Expression expr;
-
-                               if (TypeManager.IsNullableType (ltype)) {
-                                       NullableInfo info = new NullableInfo (ltype);
-
-                                       unwrap = Unwrap.Create (left, ec);
-                                       if (unwrap == null)
-                                               return null;
-
-                                       expr = Convert.ImplicitConversion (ec, right, info.UnderlyingType, loc);
-                                       if (expr != null) {
-                                               left = unwrap;
-                                               right = expr;
-                                               type = expr.Type;
-                                               return this;
-                                       }
-                               } else if (!TypeManager.IsReferenceType (ltype)) {
-                                       Binary.Error_OperatorCannotBeApplied (loc, "??", ltype, rtype);
-                                       return null;
-                               }
-
-                               expr = Convert.ImplicitConversion (ec, right, ltype, loc);
-                               if (expr != null) {
-                                       type = expr.Type;
-                                       right = expr;
-                                       return this;
-                               }
-
-                               Expression left_null = unwrap != null ? unwrap : left;
-                               expr = Convert.ImplicitConversion (ec, left_null, rtype, loc);
-                               if (expr != null) {
-                                       left = expr;
-                                       type = rtype;
-                                       return this;
-                               }
-
-                               Binary.Error_OperatorCannotBeApplied (loc, "??", ltype, rtype);
-                               return null;
-                       }
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               ILGenerator ig = ec.ig;
-
-                               Label is_null_label = ig.DefineLabel ();
-                               Label end_label = ig.DefineLabel ();
-
-                               if (unwrap != null) {
-                                       unwrap.EmitCheck (ec);
-                                       ig.Emit (OpCodes.Brfalse, is_null_label);
-
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Br, end_label);
-
-                                       ig.MarkLabel (is_null_label);
-                                       right.Emit (ec);
-
-                                       ig.MarkLabel (end_label);
-                               } else {
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Dup);
-                                       ig.Emit (OpCodes.Brtrue, end_label);
-
-                                       ig.MarkLabel (is_null_label);
-
-                                       ig.Emit (OpCodes.Pop);
-                                       right.Emit (ec);
-
-                                       ig.MarkLabel (end_label);
-                               }
-                       }
-                       protected override void CloneTo (CloneContext clonectx, Expression t)
-                       {
-                               NullCoalescingOperator target = (NullCoalescingOperator) t;
-
-                               target.left = left.Clone (clonectx);
-                               target.right = right.Clone (clonectx);
-                       }
-               }
-
-               public class LiftedUnaryMutator : ExpressionStatement
-               {
-                       public readonly UnaryMutator.Mode Mode;
-                       Expression expr, null_value;
-                       UnaryMutator underlying;
-                       Unwrap unwrap;
-
-                       public LiftedUnaryMutator (UnaryMutator.Mode mode, Expression expr, Location loc)
-                       {
-                               this.expr = expr;
-                               this.Mode = mode;
-                               this.loc = loc;
-
-                               eclass = ExprClass.Value;
-                       }
-
-                       public override Expression DoResolve (EmitContext ec)
-                       {
-                               expr = expr.Resolve (ec);
-                               if (expr == null)
-                                       return null;
-
-                               unwrap = Unwrap.Create (expr, ec);
-                               if (unwrap == null)
-                                       return null;
-
-                               underlying = (UnaryMutator) new UnaryMutator (Mode, unwrap, loc).Resolve (ec);
-                               if (underlying == null)
-                                       return null;
-
-                               null_value = new Null (expr.Type, loc).Resolve (ec);
-                               if (null_value == null)
-                                       return null;
-
-                               type = expr.Type;
-                               return this;
-                       }
-
-                       void DoEmit (EmitContext ec, bool is_expr)
-                       {
-                               ILGenerator ig = ec.ig;
-                               Label is_null_label = ig.DefineLabel ();
-                               Label end_label = ig.DefineLabel ();
-
-                               unwrap.EmitCheck (ec);
-                               ig.Emit (OpCodes.Brfalse, is_null_label);
-
-                               if (is_expr)
-                                       underlying.Emit (ec);
-                               else
-                                       underlying.EmitStatement (ec);
-                               ig.Emit (OpCodes.Br, end_label);
-
-                               ig.MarkLabel (is_null_label);
-                               if (is_expr)
-                                       null_value.Emit (ec);
-
-                               ig.MarkLabel (end_label);
-                       }
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               DoEmit (ec, true);
-                       }
-
-                       public override void EmitStatement (EmitContext ec)
-                       {
-                               DoEmit (ec, false);
-                       }
-               }
-       }
 }