expr.Emit (null);
}
+ if (expr_type == TypeManager.void_type)
+ return 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.
if (expr_type.IsPointer)
return null;
- if (expr_type.IsValueType)
+ if (TypeManager.IsValueType (expr_type))
return new BoxedCast (expr);
if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type)
return new EmptyCast (expr, target_type);
} else if (target_type == TypeManager.value_type) {
- if (expr_type.IsValueType)
+ if (TypeManager.IsValueType (expr_type))
return new BoxedCast (expr);
if (expr is NullLiteral)
- return new BoxedCast (expr);
- } else if (expr_type.IsSubclassOf (target_type)) {
+ return new NullCast (expr, target_type);
+ } else if (TypeManager.IsSubclassOf (expr_type, target_type)) {
//
// Special case: enumeration to System.Enum.
// System.Enum is not a value type, it is a class, so we need
// a boxing conversion
//
- if (expr_type.IsEnum)
+ if (expr_type.IsEnum || expr_type.IsGenericParameter)
return new BoxedCast (expr);
return new EmptyCast (expr, target_type);
// from any class-type S to any interface-type T.
if (target_type.IsInterface) {
if (TypeManager.ImplementsInterface (expr_type, target_type)){
- if (expr_type.IsClass)
+ if (expr_type.IsGenericParameter)
+ return new BoxedCast (expr, target_type);
+ else if (expr_type.IsClass)
return new EmptyCast (expr, target_type);
- else if (expr_type.IsValueType)
+ else if (TypeManager.IsValueType (expr_type) ||
+ TypeManager.IsEnumType (expr_type))
return new BoxedCast (expr, target_type);
+ else
+ return new EmptyCast (expr, target_type);
}
}
// from any delegate type to System.Delegate
if ((expr_type == TypeManager.delegate_type ||
- expr_type.IsSubclassOf (TypeManager.delegate_type)) &&
+ TypeManager.IsDelegateType (expr_type)) &&
target_type == TypeManager.delegate_type)
return new EmptyCast (expr, target_type);
// from any array-type or delegate type into System.ICloneable.
if (expr_type.IsArray ||
expr_type == TypeManager.delegate_type ||
- expr_type.IsSubclassOf (TypeManager.delegate_type))
+ TypeManager.IsDelegateType (expr_type))
if (target_type == TypeManager.icloneable_type)
return new EmptyCast (expr, target_type);
+
+ // from a generic type definition to a generic instance.
+ if (TypeManager.IsEqualGenericType (expr_type, target_type))
+ return new EmptyCast (expr, target_type);
return null;
// This is the boxed case.
//
if (target_type == TypeManager.object_type) {
- if (expr_type.IsClass || expr_type.IsValueType ||
+ if (expr_type.IsClass || TypeManager.IsValueType (expr_type) ||
expr_type.IsInterface || expr_type == TypeManager.enum_type)
return true;
- } else if (expr_type.IsSubclassOf (target_type)) {
+ } else if (TypeManager.IsSubclassOf (expr_type, target_type))
return true;
- } else {
+ else {
// Please remember that all code below actually comes
// from ImplicitReferenceConversion so make sure code remains in sync
// from any delegate type to System.Delegate
if ((expr_type == TypeManager.delegate_type ||
- expr_type.IsSubclassOf (TypeManager.delegate_type)) &&
+ TypeManager.IsDelegateType (expr_type)) &&
target_type == TypeManager.delegate_type)
if (target_type.IsAssignableFrom (expr_type))
return true;
// from any array-type or delegate type into System.ICloneable.
if (expr_type.IsArray ||
expr_type == TypeManager.delegate_type ||
- expr_type.IsSubclassOf (TypeManager.delegate_type))
+ TypeManager.IsDelegateType (expr_type))
if (target_type == TypeManager.icloneable_type)
return true;
if (expr is NullLiteral && !target_type.IsValueType &&
!TypeManager.IsEnumType (target_type))
return true;
-
+
+ // from a generic type definition to a generic instance.
+ if (TypeManager.IsEqualGenericType (expr_type, target_type))
+ return true;
}
return false;
}
Type target_type, Location loc)
{
Type expr_type = expr.Type;
-
+
//
// Attempt to do the implicit constant expression conversions
//Console.WriteLine ("Expr is {0}", expr);
//Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
- if (expr_type == target_type)
+ if (expr_type.Equals (target_type))
return true;
// First numeric conversions
if (ImplicitReferenceConversionExists (expr, target_type))
return true;
-
+
+ //
+ // Implicit Constant Expression Conversions
+ //
if (expr is IntConstant){
int value = ((IntConstant) expr).Value;
/// in a context that expects a `target_type'.
/// </summary>
static public Expression ImplicitConversion (EmitContext ec, Expression expr,
- Type target_type, Location loc)
+ Type target_type, Location loc)
{
- Type expr_type = expr.Type;
Expression e;
if (target_type == null)
Type expr_type = expr.Type;
Expression e;
- if (expr_type == target_type && !(expr is NullLiteral))
+ if (expr.eclass == ExprClass.MethodGroup){
+ if (!TypeManager.IsDelegateType (target_type)){
+ Report.Error (428, loc,
+ String.Format (
+ "Cannot convert method group to `{0}', since it is not a delegate",
+ TypeManager.CSharpName (target_type)));
+ return null;
+ }
+
+ return ImplicitDelegateCreation.Create (ec, (MethodGroupExpr) expr, target_type, loc);
+ }
+
+ if (expr_type.Equals (target_type) && !(expr is NullLiteral))
return expr;
e = ImplicitNumericConversion (ec, expr, target_type, loc);
if (value >= SByte.MinValue && value <= SByte.MaxValue)
return new SByteConstant ((sbyte) value);
} else if (target_type == TypeManager.byte_type){
- if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
+ if (value >= Byte.MinValue && value <= Byte.MaxValue)
return new ByteConstant ((byte) value);
} else if (target_type == TypeManager.short_type){
if (value >= Int16.MinValue && value <= Int16.MaxValue)
Type target_type, Location loc)
{
Expression e;
-
+
e = ImplicitConversion (ec, source, target_type, loc);
if (e != null)
return e;
"float type, use F suffix to create a float literal");
}
+ if (source is Constant){
+ Constant c = (Constant) source;
+
+ Expression.Error_ConstantValueCannotBeConverted (loc, c.AsString (), target_type);
+ return null;
+ }
+
Error_CannotImplicitConversion (loc, source.Type, target_type);
return null;
/// </summary>
public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
{
+ bool target_is_type_param = target_type.IsGenericParameter;
bool target_is_value_type = target_type.IsValueType;
if (source_type == target_type)
return true;
-
+
+ //
+ // From object to a generic parameter
+ //
+ if (source_type == TypeManager.object_type && target_is_type_param)
+ return true;
+
//
// From object to any reference type
//
//
// From any class S to any class-type T, provided S is a base class of T
//
- if (target_type.IsSubclassOf (source_type))
+ 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 (!target_type.IsSubclassOf (source_type))
+ if (!TypeManager.IsSubclassOf (target_type, source_type))
return true;
}
// From System delegate to any delegate-type
//
if (source_type == TypeManager.delegate_type &&
- target_type.IsSubclassOf (TypeManager.delegate_type))
+ TypeManager.IsDelegateType (target_type))
return true;
//
static Expression ExplicitReferenceConversion (Expression source, Type target_type)
{
Type source_type = source.Type;
+ bool target_is_type_param = target_type.IsGenericParameter;
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);
+
//
// From object to any reference type
//
if (source_type == TypeManager.object_type && !target_is_value_type)
return new ClassCast (source, target_type);
+ //
+ // Unboxing conversion.
+ //
+ if (((source_type == TypeManager.enum_type &&
+ !(source is EmptyCast)) ||
+ source_type == TypeManager.value_type) && target_is_value_type)
+ return new UnboxCast (source, target_type);
//
// From any class S to any class-type T, provided S is a base class of T
//
- if (target_type.IsSubclassOf (source_type))
+ if (TypeManager.IsSubclassOf (target_type, source_type))
return new ClassCast (source, target_type);
//
else
return 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.
// sealed, or provided T implements S.
//
if (source_type.IsInterface) {
- if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type))
- return new ClassCast (source, target_type);
- else
- return null;
+ 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 null;
}
// From an array type S with an element type Se to an array type T with an
// From System delegate to any delegate-type
//
if (source_type == TypeManager.delegate_type &&
- target_type.IsSubclassOf (TypeManager.delegate_type))
+ TypeManager.IsDelegateType (target_type))
return new ClassCast (source, target_type);
//
//
if (expr_type == TypeManager.object_type && target_type.IsValueType){
if (expr is NullLiteral){
- Report.Error (37, "Cannot convert null to value type `" +
- TypeManager.CSharpName (expr_type) + "'");
- return null;
+ //
+ // Skip the ExplicitReferenceConversion because we can not convert
+ // from Null to a ValueType, and ExplicitReference wont check against
+ // null literal explicitly
+ //
+ goto skip_explicit;
}
return new UnboxCast (expr, target_type);
+
}
-
ne = ExplicitReferenceConversion (expr, target_type);
if (ne != null)
return ne;
+ skip_explicit:
if (ec.InUnsafe){
if (target_type.IsPointer){
if (expr_type.IsPointer)
if (ne != null)
return ne;
+ if (expr is NullLiteral){
+ Report.Error (37, loc, "Cannot convert null to value type `" +
+ TypeManager.CSharpName (target_type) + "'");
+ return null;
+ }
+
Error_CannotConvertType (loc, original_expr_type, target_type);
return null;
}