+2004-04-02 Martin Baulig <martin@ximian.com>
+
+ * convert.cs: Added type parameter conversions.
+
+ * ecore.cs
+ (UnboxCast.Emit): Emit an `unbox.any' for type params.
+ (ClassCast.Emit): If the source type is a type parameter, box it.
+ If the target type is a type parameter, emit an `unbox.any'
+ instead of a `classcast'.
+
2004-04-01 Martin Baulig <martin@ximian.com>
* cs-tokenizer.cs (parse_less_than): Allow Token.DOT.
// 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 (TypeManager.IsValueType (expr_type) ||
TypeManager.IsEnumType (expr_type))
if (expr_type.IsClass || TypeManager.IsValueType (expr_type) ||
expr_type.IsInterface || expr_type == TypeManager.enum_type)
return true;
- } else if (TypeManager.IsSubclassOf (expr_type, target_type))
+ } else if (TypeManager.IsSubclassOf (expr_type, target_type))
return true;
else {
// Please remember that all code below actually comes
/// </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
//
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
//
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.
ILGenerator ig = ec.ig;
base.Emit (ec);
- ig.Emit (OpCodes.Unbox, t);
+ if (t.IsGenericParameter)
+ ig.Emit (OpCodes.Unbox_Any, t);
+ else {
+ ig.Emit (OpCodes.Unbox, t);
- LoadFromPtr (ig, t);
+ LoadFromPtr (ig, t);
+ }
}
}
{
base.Emit (ec);
- ec.ig.Emit (OpCodes.Castclass, type);
- }
-
+ if (child.Type.IsGenericParameter)
+ ec.ig.Emit (OpCodes.Box, child.Type);
+
+ if (type.IsGenericParameter)
+ ec.ig.Emit (OpCodes.Unbox_Any, type);
+ else
+ ec.ig.Emit (OpCodes.Castclass, type);
+ }
}
/// <summary>