typo
[mono.git] / mcs / mcs / convert.cs
index f5d587fe52d6d255db972d9e5c2667459d1a8518..931fe82665de4c930e87dc52bccbbcfcb7dc54ec 100644 (file)
@@ -52,18 +52,15 @@ namespace Mono.CSharp {
                }
 #endif
 
-               //
-               // From a one-dimensional array-type S[] to System.Collections.IList<S> and base
-               // interfaces of this interface.
                //
                // From a one-dimensional array-type S[] to System.Collections.IList<T> and base
                // interfaces of this interface, provided there is an implicit reference conversion
                // from S to T.
                //
-               static bool Array_To_IList (Type array, Type list)
+               static bool Array_To_IList (Type array, Type list, bool isExplicit)
                {
 #if GMCS_SOURCE
-                       if (!array.IsArray || (array.GetArrayRank () != 1) || !list.IsGenericType)
+                       if ((array.GetArrayRank () != 1) || !list.IsGenericType)
                                return false;
 
                        Type gt = list.GetGenericTypeDefinition ();
@@ -78,11 +75,14 @@ namespace Mono.CSharp {
                        if (element_type == arg_type)
                                return true;
 
+                       if (isExplicit)
+                               return ExplicitReferenceConversionExists (element_type, arg_type);
+
                        if (MyEmptyExpr == null)
                                MyEmptyExpr = new EmptyExpression ();
                        MyEmptyExpr.SetType (TypeManager.GetElementType (array));
 
-                       return ImplicitReferenceConversionCore (MyEmptyExpr, arg_type);
+                       return ImplicitReferenceConversionExists (MyEmptyExpr, arg_type);
 #else
                        return false;
 #endif
@@ -208,56 +208,31 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               static bool ExplicitTypeParameterConversionExists (Type source_type, Type target_type)
+               static Expression ExplicitTypeParameterConversion (Expression source, Type source_type, Type target_type)
                {
 #if GMCS_SOURCE
-                       if (target_type.IsInterface)
-                               return true;
-
                        if (TypeManager.IsGenericParameter (target_type)) {
                                GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
                                if (gc == null)
-                                       return false;
+                                       return null;
 
                                foreach (Type iface in gc.InterfaceConstraints) {
                                        if (!TypeManager.IsGenericParameter (iface))
                                                continue;
 
                                        if (TypeManager.IsSubclassOf (source_type, iface))
-                                               return true;
+                                               return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
                                }
                        }
-#endif
-                       return false;
-               }
-
-               static Expression ExplicitTypeParameterConversion (Expression source, Type target_type)
-               {
-#if GMCS_SOURCE
-                       Type source_type = source.Type;
 
                        if (target_type.IsInterface)
-                               return new ClassCast (source, target_type);
-
-                       if (TypeManager.IsGenericParameter (target_type)) {
-                               GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
-                               if (gc == null)
-                                       return null;
-
-                               foreach (Type iface in gc.InterfaceConstraints) {
-                                       if (!TypeManager.IsGenericParameter (iface))
-                                               continue;
-
-                                       if (TypeManager.IsSubclassOf (source_type, iface))
-                                               return new ClassCast (source, target_type);
-                               }
-                       }
+                               return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
 #endif
                        return null;
                }
 
                static EmptyExpression MyEmptyExpr;
-               static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
+               static Expression ImplicitReferenceConversion (Expression expr, Type target_type, bool explicit_cast)
                {
                        Type expr_type = expr.Type;
 
@@ -281,8 +256,15 @@ namespace Mono.CSharp {
                                return nl.ConvertImplicitly(target_type);
                        }
 
-                       if (ImplicitReferenceConversionCore (expr, target_type))
+                       if (ImplicitReferenceConversionExists (expr, target_type)) {
+                               // 
+                               // Reduce implicit reference conversion to object
+                               //
+                               if (!explicit_cast && target_type == TypeManager.object_type)
+                                       return expr;
+
                                return EmptyCast.Create (expr, target_type);
+                       }
 
                        bool use_class_cast;
                        if (ImplicitBoxingConversionExists (expr, target_type, out use_class_cast)) {
@@ -295,10 +277,23 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               static public bool ImplicitReferenceConversionCore (Expression expr, Type target_type)
+               //
+               // 6.1.6 Implicit reference conversions
+               //
+               public static bool ImplicitReferenceConversionExists (Expression expr, Type target_type)
                {
+                       if (target_type.IsValueType)
+                               return false;
+
                        Type expr_type = expr.Type;
 
+                       // from the null type to any reference-type.
+                       if (expr_type == TypeManager.null_type)
+                               return target_type != TypeManager.anonymous_method_type;
+
+                       if (TypeManager.IsGenericParameter (expr_type))
+                               return ImplicitTypeParameterConversion (expr, target_type) != null;
+
                        //
                        // notice that it is possible to write "ValueType v = 1", the ValueType here
                        // is an abstract class, and not really a value type, so we apply the same rules.
@@ -344,36 +339,44 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       // from any interface type S to interface-type T.
-                       if (expr_type.IsInterface && target_type.IsInterface) {
-                               return TypeManager.ImplementsInterface (expr_type, target_type);
-                       }
-
-                       // from an array-type S to an array-type of type T
-                       if (expr_type.IsArray && target_type.IsArray) {
-                               if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
+                       if (expr_type.IsArray) {
+                               // from an array-type S to an array-type of type T
+                               if (target_type.IsArray && expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
 
+                                       //
+                                       // Both SE and TE are reference-types
+                                       //
                                        Type expr_element_type = TypeManager.GetElementType (expr_type);
+                                       if (!TypeManager.IsReferenceType (expr_element_type))
+                                               return false;
+
+                                       Type target_element_type = TypeManager.GetElementType (target_type);
+                                       if (!TypeManager.IsReferenceType (target_element_type))
+                                               return false;
 
                                        if (MyEmptyExpr == null)
                                                MyEmptyExpr = new EmptyExpression ();
 
                                        MyEmptyExpr.SetType (expr_element_type);
-                                       Type target_element_type = TypeManager.GetElementType (target_type);
 
-                                       if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
-                                               return ImplicitStandardConversionExists (
-                                                       MyEmptyExpr, target_element_type);
+                                       return ImplicitStandardConversionExists (MyEmptyExpr, target_element_type);
                                }
-                       }
 
-                       // from an array-type to System.Array
-                       if (expr_type.IsArray && target_type == TypeManager.array_type)
-                               return true;
+                               // from an array-type to System.Array
+                               if (target_type == TypeManager.array_type)
+                                       return true;
 
-                       // from an array-type of type T to IList<T>
-                       if (expr_type.IsArray && Array_To_IList (expr_type, target_type))
-                               return true;
+                               // from an array-type of type T to IList<T>
+                               if (Array_To_IList (expr_type, target_type, false))
+                                       return true;
+
+                               return false;
+                       }
+
+                       // from any interface type S to interface-type T.
+                       if (expr_type.IsInterface && target_type.IsInterface) {
+                               return TypeManager.ImplementsInterface (expr_type, target_type);
+                       }
 
                        // from any delegate type to System.Delegate
                        if (target_type == TypeManager.delegate_type &&
@@ -424,9 +427,12 @@ namespace Mono.CSharp {
                                if (TypeManager.IsNullableType (expr_type))
                                        return TypeManager.GetTypeArguments (expr_type) [0].IsEnum;
                        }
-                       
+
                        if (TypeManager.IsSubclassOf (expr_type, target_type)) {
-                               if (TypeManager.IsGenericParameter (expr_type))
+                               //
+                               // Don't box same type arguments
+                               //
+                               if (TypeManager.IsGenericParameter (expr_type) && expr_type != target_type)
                                        return true;
 
                                return false;
@@ -451,33 +457,6 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               //
-               // Tests whether an implicit reference conversion exists between expr_type
-               // and target_type
-               //
-               public static bool ImplicitReferenceConversionExists (Expression expr, Type target_type)
-               {
-                       if (target_type.IsValueType)
-                               return false;
-
-                       Type expr_type = expr.Type;
-
-                       // from the null type to any reference-type.
-                       if (expr_type == TypeManager.null_type){
-                               return true;
-                       }
-
-                       if (TypeManager.IsGenericParameter (expr_type))
-                               return ImplicitTypeParameterConversion (expr, target_type) != null;
-
-                       bool use_class_cast;
-                       if (ImplicitReferenceConversionCore (expr, target_type) ||
-                           ImplicitBoxingConversionExists (expr, target_type, out use_class_cast))
-                               return true;
-
-                       return false;
-               }
-
                /// <summary>
                ///   Implicit Numeric Conversions.
                ///
@@ -511,13 +490,8 @@ namespace Mono.CSharp {
                                // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
                                //
                                if (real_target_type == TypeManager.int32_type || real_target_type == TypeManager.uint32_type ||
-                                       real_target_type == TypeManager.short_type || real_target_type == TypeManager.ushort_type) {
-                                       if (expr is EmptyCast) {
-                                               expr.Type = target_type;
-                                               return expr;
-                                       }
+                                   real_target_type == TypeManager.short_type || real_target_type == TypeManager.ushort_type)
                                        return EmptyCast.Create (expr, target_type);
-                               }
 
                                if (real_target_type == TypeManager.uint64_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
@@ -549,18 +523,11 @@ namespace Mono.CSharp {
                                //
                                // From ushort to int, uint, long, ulong, float, double, decimal
                                //
-                               if (real_target_type == TypeManager.int32_type || real_target_type == TypeManager.uint32_type) {
-                                       if (expr is EmptyCast) {
-                                               expr.Type = target_type;
-                                               return expr;
-                                       }
+                               if (real_target_type == TypeManager.int32_type || real_target_type == TypeManager.uint32_type)
                                        return EmptyCast.Create (expr, target_type);
-                               }
                                
                                if (real_target_type == TypeManager.uint64_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
-                               if (real_target_type == TypeManager.int32_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
                                if (real_target_type == TypeManager.int64_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
                                if (real_target_type == TypeManager.double_type)
@@ -590,11 +557,9 @@ namespace Mono.CSharp {
                                if (real_target_type == TypeManager.uint64_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
                                if (real_target_type == TypeManager.double_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
-                                                              OpCodes.Conv_R8);
+                                       return new OpcodeCast (new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un), target_type, OpCodes.Conv_R8);
                                if (real_target_type == TypeManager.float_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
-                                                              OpCodes.Conv_R4);
+                                       return new OpcodeCast (new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un), target_type, OpCodes.Conv_R4);
                                if (real_target_type == TypeManager.decimal_type)
                                        return new CastToDecimal (expr);
                        } else if (expr_type == TypeManager.int64_type){
@@ -612,11 +577,9 @@ namespace Mono.CSharp {
                                // From ulong to float, double
                                //
                                if (real_target_type == TypeManager.double_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
-                                                              OpCodes.Conv_R8);
+                                       return new OpcodeCast (new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un), target_type, OpCodes.Conv_R8);
                                if (real_target_type == TypeManager.float_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
-                                                              OpCodes.Conv_R4);
+                                       return new OpcodeCast (new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un), target_type, OpCodes.Conv_R4);
                                if (real_target_type == TypeManager.decimal_type)
                                        return new CastToDecimal (expr);
                        } else if (expr_type == TypeManager.char_type){
@@ -666,6 +629,15 @@ namespace Mono.CSharp {
                        if (ImplicitStandardConversionExists (expr, target_type))
                                return true;
 
+                       if (expr.Type == TypeManager.anonymous_method_type) {
+                               if (!TypeManager.IsDelegateType (target_type) &&
+                                       TypeManager.DropGenericTypeArguments (target_type) != TypeManager.expression_type)
+                                       return false;
+
+                               AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
+                               return ame.ImplicitStandardConversionExists (ec, target_type);
+                       }
+
                        return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null;
                }
 
@@ -701,6 +673,17 @@ namespace Mono.CSharp {
                        if (expr_type == TypeManager.void_type)
                                return false;
 
+                       if (expr.eclass == ExprClass.MethodGroup) {
+                               if (TypeManager.IsDelegateType (target_type) && RootContext.Version != LanguageVersion.ISO_1) {
+                                       MethodGroupExpr mg = expr as MethodGroupExpr;
+                                       if (mg != null) {
+                                               return DelegateCreation.ImplicitStandardConversionExists (mg, target_type) != null;
+                                       }
+                               }
+
+                               return false;
+                       }
+
                        //Console.WriteLine ("Expr is {0}", expr);
                        //Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
                        if (TypeManager.IsEqual (expr_type, target_type))
@@ -813,20 +796,13 @@ namespace Mono.CSharp {
                                        return true;
                        }
 
-                       if (expr.eclass == ExprClass.MethodGroup){
-                               if (TypeManager.IsDelegateType (target_type) && RootContext.Version != LanguageVersion.ISO_1){
-                                       MethodGroupExpr mg = expr as MethodGroupExpr;
-                                       if (mg != null){
-                                               return DelegateCreation.ImplicitStandardConversionExists (mg, target_type) != null;
-                                       }
-                               }
-
-                               return false;
-                       }
-
                        if (ImplicitReferenceConversionExists (expr, target_type))
                                return true;
 
+                       bool use_class_cast;
+                       if (ImplicitBoxingConversionExists (expr, target_type, out use_class_cast))
+                               return true;
+
                        //
                        // Implicit Constant Expression Conversions
                        //
@@ -883,15 +859,6 @@ namespace Mono.CSharp {
                        if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
                                return true;
 
-                       if (expr_type == TypeManager.anonymous_method_type){
-                               if (!TypeManager.IsDelegateType (target_type) &&
-                                       TypeManager.DropGenericTypeArguments (target_type) != TypeManager.expression_type)
-                                       return false;
-                               
-                               AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
-                               return ame.ImplicitStandardConversionExists (target_type);
-                       }
-
                        return false;
                }
 
@@ -994,8 +961,8 @@ namespace Mono.CSharp {
                        //
                        Type source_type = source.Type;
                        foreach (MethodBase mb in list){
-                               ParameterData pd = TypeManager.GetParameterData (mb);
-                               Type param_type = pd.ParameterType (0);
+                               AParametersCollection pd = TypeManager.GetParameterData (mb);
+                               Type param_type = pd.Types [0];
 
                                if (param_type == source_type)
                                        return param_type;
@@ -1112,10 +1079,24 @@ namespace Mono.CSharp {
 
                        Type source_type = source.Type;
                        EmptyExpression expr = EmptyExpression.Grab ();
+
+                       //
+                       // LAMESPEC: Undocumented IntPtr/UIntPtr conversions
+                       // IntPtr -> uint uses int
+                       // UIntPtr -> long uses ulong
+                       //
+                       if (source_type == TypeManager.intptr_type) {
+                               if (target_type == TypeManager.uint32_type)
+                                       target_type = TypeManager.int32_type;
+                       } else if (source_type == TypeManager.uintptr_type) {
+                               if (target_type == TypeManager.int64_type)
+                                       target_type = TypeManager.uint64_type;
+                       }
+
                        foreach (MethodInfo m in mg.Methods) {
-                               ParameterData pd = TypeManager.GetParameterData (m);
+                               AParametersCollection pd = TypeManager.GetParameterData (m);
                                Type return_type = TypeManager.TypeToCoreType (m.ReturnType);
-                               Type arg_type = pd.ParameterType (0);
+                               Type arg_type = pd.Types [0];
 
                                if (source_type != arg_type) {
                                        if (!ImplicitStandardConversionExists (source, arg_type)) {
@@ -1138,6 +1119,10 @@ namespace Mono.CSharp {
                                        }
                                }
 
+                               // See LAMESPEC: Exclude IntPtr -> int conversion
+                               if (source_type == TypeManager.uintptr_type && return_type == TypeManager.uint32_type)
+                                       continue;
+
                                list.Add (m);
                        }
 
@@ -1190,7 +1175,7 @@ namespace Mono.CSharp {
                        foreach (MethodInfo m in ops) {
                                if (TypeManager.TypeToCoreType (m.ReturnType) != most_specific_target)
                                        continue;
-                               if (TypeManager.GetParameterData (m).ParameterType (0) != most_specific_source)
+                               if (TypeManager.GetParameterData (m).Types [0] != most_specific_source)
                                        continue;
                                // Ambiguous: more than one conversion operator satisfies the signature.
                                if (method != null)
@@ -1215,7 +1200,16 @@ namespace Mono.CSharp {
                        MethodInfo method = null;
 
                        object o;
-                       DoubleHash hash = look_for_explicit ? explicit_conv : implicit_conv;
+                       DoubleHash hash;
+                       if (look_for_explicit) {
+                               hash = explicit_conv;
+                       } else {
+                               // Implicit user operators cannot convert to interfaces
+                               if (target.IsInterface)
+                                       return null;
+
+                               hash = implicit_conv;
+                       }                       
 
                        if (!(source is Constant) && hash.Lookup (source_type, target, out o)) {
                                method = (MethodInfo) o;
@@ -1228,7 +1222,7 @@ namespace Mono.CSharp {
                        if (method == null)
                                return null;
 
-                       Type most_specific_source = TypeManager.GetParameterData (method).ParameterType (0);
+                       Type most_specific_source = TypeManager.GetParameterData (method).Types [0];
 
                        //
                        // This will do the conversion to the best match that we
@@ -1244,7 +1238,7 @@ namespace Mono.CSharp {
                        if (source == null)
                                return null;
 
-                       return new UserCast (method, source, loc);
+                       return new UserCast (method, source, loc).DoResolve (ec);
                }
 
                /// <summary>
@@ -1284,6 +1278,11 @@ namespace Mono.CSharp {
                /// </summary>
                static public Expression ImplicitConversionStandard (EmitContext ec, Expression expr,
                                                                     Type target_type, Location loc)
+               {
+                       return ImplicitConversionStandard (ec, expr, target_type, loc, false);
+               }
+
+               static Expression ImplicitConversionStandard (EmitContext ec, Expression expr, Type target_type, Location loc, bool explicit_cast)
                {
                        Type expr_type = expr.Type;
                        Expression e;
@@ -1298,15 +1297,13 @@ namespace Mono.CSharp {
                                
                                Type target = TypeManager.GetTypeArguments (target_type) [0];
 
-                               if (TypeManager.IsNullableType (expr.Type)) {
-                                       Type etype = TypeManager.GetTypeArguments (expr.Type) [0];
+                               if (TypeManager.IsNullableType (expr_type)) {
+                                       Type etype = TypeManager.GetTypeArguments (expr_type) [0];
                                        if (TypeManager.IsEqual (etype, target))
                                                return expr;
 
-                                       e = new Nullable.LiftedConversion (
+                                       return new Nullable.LiftedConversion (
                                                expr, target_type, false, false, loc).Resolve (ec);
-                                       if (e != null)
-                                               return e;
                                } else {
                                        e = ImplicitConversion (ec, expr, target, loc);
                                        if (e != null)
@@ -1330,8 +1327,11 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (expr_type.Equals (target_type) && expr_type != TypeManager.null_type)
-                               return expr;
+                       if (expr_type.Equals (target_type)) {
+                               if (expr_type != TypeManager.null_type && expr_type != TypeManager.anonymous_method_type)
+                                       return expr;
+                               return null;
+                       }
 
                        //
                        // Attempt to do the implicit constant expression conversions
@@ -1359,15 +1359,21 @@ namespace Mono.CSharp {
                        if (e != null)
                                return e;
 
-                       e = ImplicitReferenceConversion (expr, target_type);
+                       e = ImplicitReferenceConversion (expr, target_type, explicit_cast);
                        if (e != null)
                                return e;
 
-                       if (TypeManager.IsEnumType (target_type) && expr is IntLiteral){
-                               IntLiteral i = (IntLiteral) expr;
-
-                               if (i.Value == 0)
-                                       return new EnumConstant ((Constant) expr, target_type);
+                       if (expr is IntConstant && TypeManager.IsEnumType (target_type)){
+                               Constant i = (Constant) expr;
+                               //
+                               // LAMESPEC: Conversion from any 0 constant is allowed
+                               //
+                               // An implicit enumeration conversion permits the decimal-integer-literal 0
+                               // to be converted to any enum-type and to any nullable-type whose underlying
+                               // type is an enum-type
+                               //
+                               if (i.IsDefaultValue)
+                                       return new EnumConstant (i, target_type);
                        }
 
                        if (ec.InUnsafe) {
@@ -1388,7 +1394,7 @@ namespace Mono.CSharp {
                                }
 
                                if (expr_type == TypeManager.null_type && target_type.IsPointer)
-                                       return EmptyCast.Create (NullPointer.Null, target_type);
+                                       return EmptyCast.Create (new NullPointer (loc), target_type);
                        }
 
                        if (expr_type == TypeManager.anonymous_method_type){
@@ -1693,129 +1699,40 @@ namespace Mono.CSharp {
                /// </summary>
                public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
                {
-                       bool target_is_type_param = TypeManager.IsGenericParameter (target_type);
-                       bool target_is_value_type = target_type.IsValueType;
-
-                       if (source_type == target_type)
-                               return true;
-
-                       //
-                       // From generic parameter to any type
-                       //
-                       if (TypeManager.IsGenericParameter (source_type))
-                               return ExplicitTypeParameterConversionExists (source_type, target_type);
-
-                       //
-                       // From object to a generic parameter
-                       //
-                       if (source_type == TypeManager.object_type && target_is_type_param)
-                               return true;
-
-                       //
-                       // From object to any reference type
-                       //
-                       if (source_type == TypeManager.object_type && !target_is_value_type)
-                               return true;
-
-                       //
-                       // From any class S to any class-type T, provided S is a base class of T
-                       //
-                       if (TypeManager.IsSubclassOf (target_type, source_type))
-                               return true;
-
-                       //
-                       // From any interface type S to any interface T provided S is not derived from T
-                       //
-                       if (source_type.IsInterface && target_type.IsInterface){
-                               if (!TypeManager.IsSubclassOf (target_type, source_type))
-                                       return true;
-                       }
-
-                       //
-                       // From any class type S to any interface T, provided S is not sealed
-                       // and provided S does not implement T.
-                       //
-                       if (target_type.IsInterface && !source_type.IsSealed &&
-                           !TypeManager.ImplementsInterface (source_type, target_type))
-                               return true;
-
-                       //
-                       // From any interface-type S to to any class type T, provided T is not
-                       // sealed, or provided T implements S.
-                       //
-                       if (source_type.IsInterface &&
-                           (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)))
-                               return true;
-
-
-                       if (source_type.IsInterface && IList_To_Array (source_type, target_type))
-                               return true;
-
-                       // From an array type S with an element type Se to an array type T with an
-                       // element type Te provided all the following are true:
-                       //     * S and T differe only in element type, in other words, S and T
-                       //       have the same number of dimensions.
-                       //     * Both Se and Te are reference types
-                       //     * An explicit referenc conversions exist from Se to Te
-                       //
-                       if (source_type.IsArray && target_type.IsArray) {
-                               if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
-
-                                       Type source_element_type = TypeManager.GetElementType (source_type);
-                                       Type target_element_type = TypeManager.GetElementType (target_type);
-
-                                       if (TypeManager.IsGenericParameter (source_element_type) ||
-                                           (!source_element_type.IsValueType && !target_element_type.IsValueType))
-                                               if (ExplicitReferenceConversionExists (source_element_type,
-                                                                                      target_element_type))
-                                                       return true;
-                               }
-                       }
-
-
-                       // From System.Array to any array-type
-                       if (source_type == TypeManager.array_type &&
-                           target_type.IsArray){
-                               return true;
-                       }
+                       Expression e = ExplicitReferenceConversion (null, source_type, target_type);
+                       if (e == null)
+                               return false;
 
-                       //
-                       // From System delegate to any delegate-type
-                       //
-                       if (source_type == TypeManager.delegate_type &&
-                           TypeManager.IsDelegateType (target_type))
+                       if (e == EmptyExpression.Null)
                                return true;
 
-                       return false;
+                       throw new InternalErrorException ("Invalid probing conversion result");
                }
 
                /// <summary>
                ///   Implements Explicit Reference conversions
                /// </summary>
-               static Expression ExplicitReferenceConversion (Expression source, Type target_type)
+               static Expression ExplicitReferenceConversion (Expression source, Type source_type, Type target_type)
                {
-                       Type source_type = source.Type;
-                       bool target_is_type_param = TypeManager.IsGenericParameter (target_type);
                        bool target_is_value_type = target_type.IsValueType;
 
                        //
                        // From object to a generic parameter
                        //
-                       if (source_type == TypeManager.object_type && target_is_type_param)
-                               return new UnboxCast (source, target_type);
+                       if (source_type == TypeManager.object_type && TypeManager.IsGenericParameter (target_type))
+                               return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
 
                        //
                        // Explicit type parameter conversion.
                        //
-
                        if (TypeManager.IsGenericParameter (source_type))
-                               return ExplicitTypeParameterConversion (source, target_type);
+                               return ExplicitTypeParameterConversion (source, source_type, target_type);
 
                        //
                        // From object to any reference type
                        //
                        if (source_type == TypeManager.object_type && !target_is_value_type)
-                               return new ClassCast (source, target_type);
+                               return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
 
                        //
                        // Unboxing conversion.
@@ -1823,34 +1740,21 @@ namespace Mono.CSharp {
                        if (((source_type == TypeManager.enum_type &&
                                !(source is TypeCast)) ||
                                source_type == TypeManager.value_type) && target_is_value_type)
-                               return new UnboxCast (source, target_type);
+                               return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
 
                        //
                        // From any class S to any class-type T, provided S is a base class of T
                        //
                        if (TypeManager.IsSubclassOf (target_type, source_type))
-                               return new ClassCast (source, target_type);
-
-                       //
-                       // From any interface type S to any interface T provided S is not derived from T
-                       //
-                       if (source_type.IsInterface && target_type.IsInterface){
-                               if (TypeManager.ImplementsInterface (source_type, target_type))
-                                       return null;
-                               else
-                                       return new ClassCast (source, target_type);
-                       }
+                               return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
 
                        //
                        // From any class type S to any interface T, provides S is not sealed
                        // and provided S does not implement T.
                        //
-                       if (target_type.IsInterface && !source_type.IsSealed) {
-                               if (TypeManager.ImplementsInterface (source_type, target_type))
-                                       return null;
-                               else
-                                       return new ClassCast (source, target_type);
-
+                       if (target_type.IsInterface && !source_type.IsSealed &&
+                               !TypeManager.ImplementsInterface (source_type, target_type)) {
+                               return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
                        }
 
                        //
@@ -1860,9 +1764,9 @@ namespace Mono.CSharp {
                        if (source_type.IsInterface) {
                                if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)) {
                                        if (target_type.IsClass)
-                                               return new ClassCast (source, target_type);
-                                       else
-                                               return new UnboxCast (source, target_type);
+                                               return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
+
+                                       return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
                                }
 
                                //
@@ -1870,44 +1774,59 @@ namespace Mono.CSharp {
                                // array type S[], provided there is an implicit or explicit reference conversion from S to T.
                                //
                                if (IList_To_Array (source_type, target_type))
-                                       return new ClassCast (source, target_type);
+                                       return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
 
                                return null;
                        }
 
-                       // From an array type S with an element type Se to an array type T with an
-                       // element type Te provided all the following are true:
-                       //     * S and T differe only in element type, in other words, S and T
-                       //       have the same number of dimensions.
-                       //     * Both Se and Te are reference types
-                       //     * An explicit referenc conversions exist from Se to Te
-                       //
-                       if (source_type.IsArray && target_type.IsArray) {
-                               if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
+                       if (source_type.IsArray) {
+                               if (target_type.IsArray) {
+                                       //
+                                       // From System.Array to any array-type
+                                       //
+                                       if (source_type == TypeManager.array_type)
+                                               return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
 
-                                       Type source_element_type = TypeManager.GetElementType (source_type);
-                                       Type target_element_type = TypeManager.GetElementType (target_type);
+                                       //
+                                       // From an array type S with an element type Se to an array type T with an
+                                       // element type Te provided all the following are true:
+                                       //     * S and T differe only in element type, in other words, S and T
+                                       //       have the same number of dimensions.
+                                       //     * Both Se and Te are reference types
+                                       //     * An explicit reference conversions exist from Se to Te
+                                       //
+                                       if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
+
+                                               source_type = TypeManager.GetElementType (source_type);
+                                               if (!TypeManager.IsReferenceType (source_type))
+                                                       return null;
 
-                                       if (!source_element_type.IsValueType && !target_element_type.IsValueType)
-                                               if (ExplicitReferenceConversionExists (source_element_type,
-                                                                                      target_element_type))
-                                                       return new ClassCast (source, target_type);
+                                               Type target_type_element = TypeManager.GetElementType (target_type);
+                                               if (!TypeManager.IsReferenceType (target_type_element))
+                                                       return null;
+
+                                               if (ExplicitReferenceConversionExists (source_type, target_type_element))
+                                                       return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
+                                                       
+                                               return null;
+                                       }
                                }
-                       }
 
+                               //
+                               // From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, 
+                               // provided that there is an explicit reference conversion from S to T
+                               //
+                               if (Array_To_IList (source_type, target_type, true))
+                                       return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
 
-                       // From System.Array to any array-type
-                       if (source_type == TypeManager.array_type &&
-                           target_type.IsArray) {
-                               return new ClassCast (source, target_type);
+                               return null;
                        }
 
                        //
                        // From System delegate to any delegate-type
                        //
-                       if (source_type == TypeManager.delegate_type &&
-                           TypeManager.IsDelegateType (target_type))
-                               return new ClassCast (source, target_type);
+                       if (source_type == TypeManager.delegate_type && TypeManager.IsDelegateType (target_type))
+                               return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
 
                        return null;
                }
@@ -1922,7 +1841,7 @@ namespace Mono.CSharp {
                        Type expr_type = expr.Type;
 
                        // Explicit conversion includes implicit conversion and it used for enum underlying types too
-                       Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc);
+                       Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true);
                        if (ne != null)
                                return ne;
 
@@ -1952,11 +1871,11 @@ namespace Mono.CSharp {
                                //
                                // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
                                //
-                if (expr_type == TypeManager.intptr_type || expr_type == TypeManager.uintptr_type) {
+                               if (expr_type == TypeManager.intptr_type || expr_type == TypeManager.uintptr_type) {
                                        ne = ExplicitUserConversion (ec, expr, TypeManager.GetEnumUnderlyingType (target_type), loc);
                                        if (ne != null)
                                                return ExplicitConversionCore (ec, ne, target_type, loc);
-                }
+                               }
                                
                                return null;
                        }
@@ -1971,7 +1890,7 @@ namespace Mono.CSharp {
                        // null literal explicitly
                        //
                        if (expr_type != TypeManager.null_type){
-                               ne = ExplicitReferenceConversion (expr, target_type);
+                               ne = ExplicitReferenceConversion (expr, expr_type, target_type);
                                if (ne != null)
                                        return ne;
                        }
@@ -1995,13 +1914,12 @@ namespace Mono.CSharp {
 
                                if (expr_type == TypeManager.sbyte_type ||
                                        expr_type == TypeManager.short_type ||
-                                       expr_type == TypeManager.int32_type ||
-                                       expr_type == TypeManager.int64_type)
+                                       expr_type == TypeManager.int32_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
 
                                if (expr_type == TypeManager.ushort_type ||
                                        expr_type == TypeManager.uint32_type ||
-                                       expr_type == TypeManager.uint64_type ||
+                                       expr_type == TypeManager.uint64_type || expr_type == TypeManager.int64_type ||
                                        expr_type == TypeManager.byte_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
                        }
@@ -2019,11 +1937,8 @@ namespace Mono.CSharp {
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
                                else if (target_type == TypeManager.uint32_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
-                               else if (target_type == TypeManager.uint64_type)
+                               else if (target_type == TypeManager.uint64_type || target_type == TypeManager.int64_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
-                               else if (target_type == TypeManager.int64_type){
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
-                               }
                        }
                        return null;
                }
@@ -2046,7 +1961,7 @@ namespace Mono.CSharp {
                        if (ne != null)
                                return ne;
 
-                       ne = ExplicitReferenceConversion (expr, target_type);
+                       ne = ExplicitReferenceConversion (expr, expr.Type, target_type);
                        if (ne != null)
                                return ne;