public static Expression ImplicitTypeParameterConversion (Expression expr, TypeParameterSpec expr_type, TypeSpec target_type) { // // From T to a type parameter U, provided T depends on U // if (target_type.IsGenericParameter) { if (expr_type.TypeArguments != null) { foreach (var targ in expr_type.TypeArguments) { if (!TypeSpecComparer.Override.IsEqual (target_type, targ)) continue; if (expr == null) return EmptyExpression.Null; if (expr_type.IsReferenceType && !((TypeParameterSpec)target_type).IsReferenceType) return new BoxedCast (expr, target_type); return new ClassCast (expr, target_type); } } return null; } // // LAMESPEC: From T to dynamic type because it's like T to object // if (target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { if (expr == null) return EmptyExpression.Null; 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 (it cannot contain dynamic or be of dynamic type) // From T to any interface implemented by C // var base_type = expr_type.GetEffectiveBase (); if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type, true)) { if (expr == null) return EmptyExpression.Null; if (expr_type.IsReferenceType) return new ClassCast (expr, target_type); return new BoxedCast (expr, target_type); } if (target_type.IsInterface && expr_type.IsConvertibleToInterface (target_type)) { if (expr == null) return EmptyExpression.Null; if (expr_type.IsReferenceType) return new ClassCast (expr, target_type); return new BoxedCast (expr, target_type); } return null; }
static Expression ExplicitTypeParameterConversionToT (Expression source, TypeSpec source_type, TypeParameterSpec target_type) { // // From the effective base class C of T to T and from any base class of C to T // var effective = target_type.GetEffectiveBase (); if (TypeSpecComparer.IsEqual (effective, source_type) || TypeSpec.IsBaseClass (effective, source_type, false)) return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); return null; }