return null;
}
+ //
+ // LAMESPEC: From T to dynamic type because it's like T to object
+ //
+ if (target_type == InternalType.Dynamic) {
+ if (expr_type.IsReferenceType)
+ return new ClassCast (expr, target_type);
+
+ return new BoxedCast (expr, target_type);
+ }
+
//
// From T to its effective base class C
- // From T to any base class of C
+ // From T to any base class of C (it cannot contain dynamic of be of dynamic type)
// From T to any interface implemented by C
//
var base_type = expr_type.GetEffectiveBase ();
- if (base_type == target_type || TypeManager.IsSubclassOf (base_type, target_type) || base_type.ImplementsInterface (target_type)) {
+ if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type)) {
if (expr_type.IsReferenceType)
return new ClassCast (expr, target_type);
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
}
}
-
+/*
if (target_tp.Interfaces != null) {
foreach (TypeSpec iface in target_tp.Interfaces) {
if (!TypeManager.IsGenericParameter (iface))
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
}
}
-
+*/
return null;
}
TypeSpec expr_type = expr.Type;
// from the null type to any reference-type.
- if (expr_type == TypeManager.null_type)
+ if (expr_type == InternalType.Null)
return target_type != InternalType.AnonymousMethod;
if (TypeManager.IsGenericParameter (expr_type))
}
//
- // 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.
+ // Implicit reference conversions (no-boxing) to object or dynamic
//
if (target_type == TypeManager.object_type || target_type == InternalType.Dynamic) {
- //
- // A pointer type cannot be converted to object
- //
- if (expr_type.IsPointer)
- return false;
-
- if (TypeManager.IsValueType (expr_type))
- return false;
-
- if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type || expr_type.IsDelegate || expr_type.Kind == MemberKind.ArrayType) {
- // No mcs internal types are convertible
- return true; // expr_type.MetaInfo.Module != typeof (Convert).Module;
- }
-
- // From anything to dynamic
- if (target_type == InternalType.Dynamic)
+ switch (expr_type.Kind) {
+ case MemberKind.Class:
+ case MemberKind.Interface:
+ case MemberKind.Delegate:
+ case MemberKind.ArrayType:
return true;
+ }
- // From dynamic to object
- if (expr_type == InternalType.Dynamic)
- return true;
+ return expr_type == InternalType.Dynamic;
+ }
- return false;
- } else if (target_type == TypeManager.value_type) {
+ if (target_type == TypeManager.value_type) {
return expr_type == TypeManager.enum_type;
- } else if (TypeManager.IsSubclassOf (expr_type, target_type)) {
+ } else if (expr_type == target_type || TypeSpec.IsBaseClass (expr_type, target_type, true)) {
//
// Special case: enumeration to System.Enum.
// System.Enum is not a value type, it is a class, so we need
(expr_type == TypeManager.delegate_type || expr_type.IsDelegate))
return true;
- if (TypeManager.IsEqual (expr_type, target_type))
- return true;
-
return false;
}
return res;
}
- if (TypeManager.IsSubclassOf (expr_type, target_type)) {
+ if (TypeSpec.IsBaseClass (expr_type, target_type, false)) {
//
// Don't box same type arguments
//
//
// From null to any nullable type
//
- if (expr_type == TypeManager.null_type)
+ if (expr_type == InternalType.Null)
return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location);
// S -> T?
/// Determines if a standard implicit conversion exists from
/// expr_type to target_type
///
- /// ec should point to a real EmitContext if expr.Type is TypeManager.anonymous_method_type.
/// </summary>
public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type)
{
TypeSpec expr_type = expr.Type;
- if (expr_type == TypeManager.null_type) {
- NullLiteral nl = expr as NullLiteral;
- if (nl != null)
- return nl.ConvertImplicitly (null, target_type) != null;
- }
+ NullLiteral nl = expr as NullLiteral;
+ if (nl != null)
+ return nl.ConvertImplicitly (null, target_type) != null;
if (expr_type == TypeManager.void_type)
return false;
- if (TypeManager.IsEqual (expr_type, target_type))
+ if (expr_type == target_type)
return true;
+ // Implicit dynamic conversion
+ if (expr_type == InternalType.Dynamic) {
+ switch (target_type.Kind) {
+ case MemberKind.ArrayType:
+ case MemberKind.Class:
+ case MemberKind.Struct:
+ case MemberKind.Delegate:
+ case MemberKind.Enum:
+ case MemberKind.Interface:
+ case MemberKind.TypeParameter:
+ return true;
+ }
+
+ return false;
+ }
+
if (TypeManager.IsNullableType (target_type)) {
return ImplicitNulableConversion (null, expr, target_type) != null;
}
if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
return true;
-
+
//
// Implicit Constant Expression Conversions
//
if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)) {
var i = (IntegralConstant) expr;
//
- // LAMESPEC: csc allows any constand like 0 values to be converted, including const float f = 0.0
+ // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
//
// An implicit enumeration conversion permits the decimal-integer-literal 0
// to be converted to any enum-type and to any nullable-type whose underlying
return UserDefinedConversion (ec, source, target, false, loc);
}
- static void FindApplicableUserDefinedConversionOperators (MethodSpec[] operators, Expression source, TypeSpec target, bool implicitOnly, ref List<MethodSpec> candidates)
+ static void FindApplicableUserDefinedConversionOperators (IList<MemberSpec> operators, Expression source, TypeSpec target, bool implicitOnly, ref List<MethodSpec> candidates)
{
//
// LAMESPEC: Undocumented IntPtr/UIntPtr conversions
Expression texpr = null;
- foreach (var op in operators) {
+ foreach (MethodSpec op in operators) {
// Can be null because MemberCache.GetUserOperator does not resize the array
if (op == null)
TypeSpec expr_type = expr.Type;
Expression e;
- if (expr_type.Equals (target_type)) {
- if (expr_type != TypeManager.null_type && expr_type != InternalType.AnonymousMethod)
+ if (expr_type == target_type) {
+ if (expr_type != InternalType.Null && expr_type != InternalType.AnonymousMethod)
return expr;
return null;
}
- if (TypeSpecComparer.Variant.IsEqual (expr_type, target_type)) {
- return expr;
+ if (expr_type == InternalType.Dynamic) {
+ switch (target_type.Kind) {
+ case MemberKind.ArrayType:
+ case MemberKind.Class:
+ if (target_type == TypeManager.object_type)
+ return EmptyCast.Create (expr, target_type);
+
+ goto case MemberKind.Struct;
+ case MemberKind.Struct:
+ case MemberKind.Delegate:
+ case MemberKind.Enum:
+ case MemberKind.Interface:
+ case MemberKind.TypeParameter:
+ Arguments args = new Arguments (1);
+ args.Add (new Argument (expr));
+ return new DynamicConversion (target_type, 0, args, loc).Resolve (ec);
+ }
+
+ return null;
}
if (TypeManager.IsNullableType (target_type))
if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)){
var i = (IntegralConstant) expr;
//
- // LAMESPEC: csc allows any constand like 0 values to be converted, including const float f = 0.0
+ // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
//
// An implicit enumeration conversion permits the decimal-integer-literal 0
// to be converted to any enum-type and to any nullable-type whose underlying
}
}
- if (expr_type == TypeManager.null_type && target_type.IsPointer)
+ if (expr_type == InternalType.Null && target_type.IsPointer)
return EmptyCast.Create (new NullPointer (loc), target_type);
}
if (e != null)
return e;
- if (source.Type == InternalType.Dynamic) {
- Arguments args = new Arguments (1);
- args.Add (new Argument (source));
- return new DynamicConversion (target_type, 0, args, loc).Resolve (ec);
- }
-
source.Error_ValueCannotBeConverted (ec, loc, target_type, false);
return null;
}
//
// From any class S to any class-type T, provided S is a base class of T
//
- if (TypeManager.IsSubclassOf (target_type, source_type))
+ if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true))
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
//
// from Null to a ValueType, and ExplicitReference wont check against
// null literal explicitly
//
- if (expr_type != TypeManager.null_type){
+ if (expr_type != InternalType.Null) {
ne = ExplicitReferenceConversion (expr, expr_type, target_type);
if (ne != null)
return ne;