2007-12-06 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / convert.cs
index b98dc63e25cf22fa4ce6b86888371db86c1985fe..a2820a1442416f48ba62920f87b1e11b13cbbb2f 100644 (file)
@@ -349,13 +349,6 @@ namespace Mono.CSharp {
                                        return !TypeManager.IsGenericParameter (expr_type) &&
                                                !TypeManager.IsValueType (expr_type);
                                }
-                               
-                               if (!TypeManager.IsGenericType (target_type) && !TypeManager.IsGenericType (expr_type)) {
-                                       foreach (Type iface in TypeManager.GetInterfaces (target_type)) {
-                                               if (TypeManager.ImplementsInterface (expr_type, iface))
-                                                       return true;
-                                       }
-                               }
                        }
 
                        // from any interface type S to interface-type T.
@@ -411,12 +404,10 @@ namespace Mono.CSharp {
                                                                   out bool use_class_cast)
                {
                        Type expr_type = expr.Type;
-
                        use_class_cast = false;
-
+                       
                        //
-                       // 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.
+                       // From any value-type to the type object.
                        //
                        if (target_type == TypeManager.object_type) {
                                //
@@ -426,15 +417,29 @@ namespace Mono.CSharp {
                                        return false;
 
                                return TypeManager.IsValueType (expr_type);
-                       } else if (target_type == TypeManager.value_type) {
+                       }
+                       
+                       //
+                       // From any value-type to the type System.ValueType.
+                       //
+                       if (target_type == TypeManager.value_type)
                                return TypeManager.IsValueType (expr_type);
-                       } else if (TypeManager.IsSubclassOf (expr_type, target_type)) {
+
+                       if (target_type == TypeManager.enum_type) {
                                //
-                               // Special case: enumeration to System.Enum.
-                               // System.Enum is not a value type, it is a class, so we need
-                               // a boxing conversion
+                               // From any enum-type to the type System.Enum.
                                //
-                               if (expr_type.IsEnum || TypeManager.IsGenericParameter (expr_type))
+                               if (expr_type.IsEnum)
+                                       return true;
+                               //
+                               // From any nullable-type with an underlying enum-type to the type System.Enum
+                               //
+                               if (TypeManager.IsNullableType (expr_type))
+                                       return TypeManager.GetTypeArguments (expr_type) [0].IsEnum;
+                       }
+                       
+                       if (TypeManager.IsSubclassOf (expr_type, target_type)) {
+                               if (TypeManager.IsGenericParameter (expr_type))
                                        return true;
 
                                return false;
@@ -1957,10 +1962,12 @@ namespace Mono.CSharp {
                                return new UnboxCast (expr, target_type);
 
                        if (TypeManager.IsEnumType (expr_type)) {
-                               if (expr is EnumConstant)
-                                       return ExplicitConversionCore (ec, ((EnumConstant) expr).Child, target_type, loc);
+                               Expression underlying = EmptyCast.Create (expr, TypeManager.EnumToUnderlying (expr_type));
+                               expr = ExplicitConversionCore (ec, underlying, target_type, loc);
+                               if (expr != null)
+                                       return expr;
 
-                               return ExplicitConversionCore (ec, EmptyCast.Create (expr, TypeManager.EnumToUnderlying (expr_type)), target_type, loc);
+                               return ExplicitUserConversion (ec, underlying, target_type, loc);                               
                        }
 
                        if (TypeManager.IsEnumType (target_type)){
@@ -1970,6 +1977,17 @@ namespace Mono.CSharp {
                                Expression ce = ExplicitConversionCore (ec, expr, TypeManager.EnumToUnderlying (target_type), loc);
                                if (ce != null)
                                        return EmptyCast.Create (ce, target_type);
+                               
+                               //
+                               // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
+                               //
+                if (expr_type == TypeManager.intptr_type || expr_type == TypeManager.uintptr_type) {
+                                       ne = ExplicitUserConversion (ec, expr, TypeManager.EnumToUnderlying (target_type), loc);
+                                       if (ne != null)
+                                               return ExplicitConversionCore (ec, ne, target_type, loc);
+                }
+                               
+                               return null;
                        }
 
                        ne = ExplicitNumericConversion (expr, target_type);
@@ -1992,11 +2010,7 @@ namespace Mono.CSharp {
                                if (ne != null)
                                        return ne;
                        }
-
-                       ne = ExplicitUserConversion (ec, expr, target_type, loc);
-                       if (ne != null)
-                               return ne;
-
+                       
                        return null;
                }
 
@@ -2100,15 +2114,17 @@ namespace Mono.CSharp {
                        } else if (TypeManager.IsNullableType (expr_type)) {
                                Expression source = Nullable.Unwrap.Create (expr, ec);
                                if (source != null) {
-                                       e = ExplicitConversionCore (ec, source, target_type, loc);
-                                       if (e != null)
-                                               return e;
+                                       return ExplicitConversion (ec, source, target_type, loc);
                                }
                        }
 #endif
                        e = ExplicitConversionCore (ec, expr, target_type, loc);
                        if (e != null)
                                return e;
+                       
+                       e = ExplicitUserConversion (ec, expr, target_type, loc);
+                       if (e != null)
+                               return e;                       
 
                        expr.Error_ValueCannotBeConverted (ec, loc, target_type, true);
                        return null;