2
// conversion.cs: various routines for implementing conversions.
5
// Miguel de Icaza (miguel@ximian.com)
6
// Ravi Pratap (ravi@ximian.com)
7
// Marek Safar (marek.safar@gmail.com)
9
// Copyright 2001, 2002, 2003 Ximian, Inc.
10
// Copyright 2003-2008 Novell, Inc.
11
// Copyright 2011 Xamarin Inc (http://www.xamarin.com)
15
using System.Collections.Generic;
18
using IKVM.Reflection.Emit;
20
using System.Reflection.Emit;
23
namespace Mono.CSharp {
26
// A container class for all the conversion operations
31
// From a one-dimensional array-type S[] to System.Collections.IList<T> and base
32
// interfaces of this interface, provided there is an implicit reference conversion
35
static bool ArrayToIList (ArrayContainer array, TypeSpec list, bool isExplicit)
37
if (array.Rank != 1 || !list.IsGenericIterateInterface)
40
var arg_type = list.TypeArguments[0];
41
if (array.Element == arg_type)
45
// Reject conversion from T[] to IList<U> even if T has U dependency
47
if (arg_type.IsGenericParameter)
51
return ExplicitReferenceConversionExists (array.Element, arg_type);
53
return ImplicitReferenceConversionExists (array.Element, arg_type);
56
static bool IList_To_Array(TypeSpec list, ArrayContainer array)
58
if (array.Rank != 1 || !list.IsGenericIterateInterface)
61
var arg_type = list.TypeArguments[0];
62
if (array.Element == arg_type)
65
return ImplicitReferenceConversionExists (array.Element, arg_type) || ExplicitReferenceConversionExists (array.Element, arg_type);
68
public static Expression ImplicitTypeParameterConversion (Expression expr, TypeParameterSpec expr_type, TypeSpec target_type)
71
// From T to a type parameter U, provided T depends on U
73
if (target_type.IsGenericParameter) {
74
if (expr_type.TypeArguments != null) {
75
foreach (var targ in expr_type.TypeArguments) {
76
if (!TypeSpecComparer.Override.IsEqual (target_type, targ))
80
return EmptyExpression.Null;
82
if (expr_type.IsReferenceType && !((TypeParameterSpec)target_type).IsReferenceType)
83
return new BoxedCast (expr, target_type);
85
return new ClassCast (expr, target_type);
93
// LAMESPEC: From T to dynamic type because it's like T to object
95
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
97
return EmptyExpression.Null;
99
if (expr_type.IsReferenceType)
100
return new ClassCast (expr, target_type);
102
return new BoxedCast (expr, target_type);
106
// From T to its effective base class C
107
// From T to any base class of C (it cannot contain dynamic or be of dynamic type)
108
// From T to any interface implemented by C
110
var base_type = expr_type.GetEffectiveBase ();
111
if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type, true)) {
113
return EmptyExpression.Null;
115
if (expr_type.IsReferenceType)
116
return new ClassCast (expr, target_type);
118
return new BoxedCast (expr, target_type);
121
if (target_type.IsInterface && expr_type.IsConvertibleToInterface (target_type)) {
123
return EmptyExpression.Null;
125
if (expr_type.IsReferenceType)
126
return new ClassCast (expr, target_type);
128
return new BoxedCast (expr, target_type);
134
static Expression ExplicitTypeParameterConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
136
var target_tp = target_type as TypeParameterSpec;
137
if (target_tp != null) {
138
if (target_tp.TypeArguments != null) {
139
foreach (var targ in target_tp.TypeArguments) {
140
if (!TypeSpecComparer.Override.IsEqual (source_type, targ))
143
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
147
if (target_tp.Interfaces != null) {
148
foreach (TypeSpec iface in target_tp.Interfaces) {
149
if (!TypeManager.IsGenericParameter (iface))
152
if (TypeManager.IsSubclassOf (source_type, iface))
153
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
160
if (target_type.IsInterface)
161
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
166
public static Expression ImplicitReferenceConversion (Expression expr, TypeSpec target_type, bool explicit_cast)
168
TypeSpec expr_type = expr.Type;
170
if (expr_type.Kind == MemberKind.TypeParameter)
171
return ImplicitTypeParameterConversion (expr, (TypeParameterSpec) expr.Type, target_type);
174
// from the null type to any reference-type.
176
NullLiteral nl = expr as NullLiteral;
178
return nl.ConvertImplicitly (target_type);
181
if (ImplicitReferenceConversionExists (expr_type, target_type)) {
183
// Avoid wrapping implicitly convertible reference type
188
return EmptyCast.Create (expr, target_type);
195
// Implicit reference conversions
197
public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type)
199
return ImplicitReferenceConversionExists (expr_type, target_type, true);
202
public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter)
204
// It's here only to speed things up
205
if (target_type.IsStruct)
208
switch (expr_type.Kind) {
209
case MemberKind.TypeParameter:
210
return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null &&
211
(!refOnlyTypeParameter || TypeSpec.IsReferenceType (expr_type));
213
case MemberKind.Class:
215
// From any class-type to dynamic (+object to speed up common path)
217
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
220
if (target_type.IsClass) {
222
// Identity conversion, including dynamic erasure
224
if (TypeSpecComparer.IsEqual (expr_type, target_type))
228
// From any class-type S to any class-type T, provided S is derived from T
230
return TypeSpec.IsBaseClass (expr_type, target_type, true);
234
// From any class-type S to any interface-type T, provided S implements T
236
if (target_type.IsInterface)
237
return expr_type.ImplementsInterface (target_type, true);
241
case MemberKind.ArrayType:
243
// Identity array conversion
245
if (expr_type == target_type)
249
// From any array-type to System.Array
251
switch (target_type.BuiltinType) {
252
case BuiltinTypeSpec.Type.Array:
253
case BuiltinTypeSpec.Type.Object:
254
case BuiltinTypeSpec.Type.Dynamic:
258
var expr_type_array = (ArrayContainer) expr_type;
259
var target_type_array = target_type as ArrayContainer;
262
// From an array-type S to an array-type of type T
264
if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) {
267
// Both SE and TE are reference-types. TE check is defered
268
// to ImplicitReferenceConversionExists
270
TypeSpec expr_element_type = expr_type_array.Element;
271
if (!TypeSpec.IsReferenceType (expr_element_type))
275
// An implicit reference conversion exists from SE to TE
277
return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element);
281
// From any array-type to the interfaces it implements
283
if (target_type.IsInterface) {
284
if (expr_type.ImplementsInterface (target_type, false))
287
// from an array-type of type T to IList<T>
288
if (ArrayToIList (expr_type_array, target_type, false))
294
case MemberKind.Delegate:
296
// From any delegate-type to System.Delegate (and its base types)
298
switch (target_type.BuiltinType) {
299
case BuiltinTypeSpec.Type.Delegate:
300
case BuiltinTypeSpec.Type.MulticastDelegate:
301
case BuiltinTypeSpec.Type.Object:
302
case BuiltinTypeSpec.Type.Dynamic:
307
// Identity conversion, including dynamic erasure
309
if (TypeSpecComparer.IsEqual (expr_type, target_type))
313
// From any delegate-type to the interfaces it implements
314
// From any reference-type to an delegate type if is variance-convertible
316
return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type);
318
case MemberKind.Interface:
320
// Identity conversion, including dynamic erasure
322
if (TypeSpecComparer.IsEqual (expr_type, target_type))
326
// From any interface type S to interface-type T
327
// From any reference-type to an interface if is variance-convertible
329
if (target_type.IsInterface)
330
return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true);
332
return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
334
case MemberKind.InternalCompilerType:
336
// from the null literal to any reference-type.
338
if (expr_type == InternalType.NullLiteral) {
339
// Exlude internal compiler types
340
if (target_type.Kind == MemberKind.InternalCompilerType)
341
return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
343
return TypeSpec.IsReferenceType (target_type);
347
// Implicit dynamic conversion
349
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
350
switch (target_type.Kind) {
351
case MemberKind.ArrayType:
352
case MemberKind.Class:
353
case MemberKind.Delegate:
354
case MemberKind.Interface:
355
case MemberKind.TypeParameter:
359
// dynamic to __arglist
360
if (target_type == InternalType.Arglist)
372
public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
374
switch (target_type.BuiltinType) {
376
// From any non-nullable-value-type to the type object and dynamic
378
case BuiltinTypeSpec.Type.Object:
379
case BuiltinTypeSpec.Type.Dynamic:
381
// From any non-nullable-value-type to the type System.ValueType
383
case BuiltinTypeSpec.Type.ValueType:
385
// No ned to check for nullable type as underlying type is always convertible
387
if (!TypeSpec.IsValueType (expr_type))
390
return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
392
case BuiltinTypeSpec.Type.Enum:
394
// From any enum-type to the type System.Enum.
396
if (expr_type.IsEnum)
397
return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
403
// From a nullable-type to a reference type, if a boxing conversion exists from
404
// the underlying type to the reference type
406
if (expr_type.IsNullableType) {
407
if (!TypeSpec.IsReferenceType (target_type))
410
var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
412
// "cast" underlying type to target type to emit correct InvalidCastException when
413
// underlying hierarchy changes without recompilation
414
if (res != null && expr != null)
415
res = new UnboxCast (res, target_type);
421
// A value type has a boxing conversion to an interface type I if it has a boxing conversion
422
// to an interface or delegate type I0 and I0 is variance-convertible to I
424
if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) {
425
return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
431
public static Expression ImplicitNulableConversion (ResolveContext ec, Expression expr, TypeSpec target_type)
433
TypeSpec expr_type = expr.Type;
436
// From null to any nullable type
438
if (expr_type == InternalType.NullLiteral)
439
return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location);
442
TypeSpec t_el = Nullable.NullableInfo.GetUnderlyingType (target_type);
445
if (expr_type.IsNullableType)
446
expr_type = Nullable.NullableInfo.GetUnderlyingType (expr_type);
449
// Predefined implicit identity or implicit numeric conversion
450
// has to exist between underlying type S and underlying type T
453
// conversion exists only mode
455
if (TypeSpecComparer.IsEqual (expr_type, t_el))
456
return EmptyExpression.Null;
458
if (expr is Constant)
459
return ((Constant) expr).ConvertImplicitly (t_el);
461
return ImplicitNumericConversion (null, expr_type, t_el);
465
if (expr_type != expr.Type)
466
unwrap = Nullable.Unwrap.Create (expr);
470
Expression conv = unwrap;
471
if (!TypeSpecComparer.IsEqual (expr_type, t_el)) {
472
if (conv is Constant)
473
conv = ((Constant)conv).ConvertImplicitly (t_el);
475
conv = ImplicitNumericConversion (conv, expr_type, t_el);
481
if (expr_type != expr.Type)
482
return new Nullable.Lifted (conv, unwrap, target_type).Resolve (ec);
484
return Nullable.Wrap.Create (conv, target_type);
488
/// Implicit Numeric Conversions.
490
/// expr is the expression to convert, returns a new expression of type
491
/// target_type or null if an implicit conversion is not possible.
493
public static Expression ImplicitNumericConversion (Expression expr, TypeSpec target_type)
495
return ImplicitNumericConversion (expr, expr.Type, target_type);
498
public static bool ImplicitNumericConversionExists (TypeSpec expr_type, TypeSpec target_type)
500
return ImplicitNumericConversion (null, expr_type, target_type) != null;
503
static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
505
switch (expr_type.BuiltinType) {
506
case BuiltinTypeSpec.Type.SByte:
508
// From sbyte to short, int, long, float, double, decimal
510
switch (target_type.BuiltinType) {
511
case BuiltinTypeSpec.Type.Int:
512
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
513
case BuiltinTypeSpec.Type.Long:
514
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
515
case BuiltinTypeSpec.Type.Double:
516
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
517
case BuiltinTypeSpec.Type.Float:
518
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
519
case BuiltinTypeSpec.Type.Short:
520
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
521
case BuiltinTypeSpec.Type.Decimal:
522
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
527
case BuiltinTypeSpec.Type.Byte:
529
// From byte to short, ushort, int, uint, long, ulong, float, double, decimal
531
switch (target_type.BuiltinType) {
532
case BuiltinTypeSpec.Type.Int:
533
case BuiltinTypeSpec.Type.UInt:
534
case BuiltinTypeSpec.Type.Short:
535
case BuiltinTypeSpec.Type.UShort:
536
return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
537
case BuiltinTypeSpec.Type.ULong:
538
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
539
case BuiltinTypeSpec.Type.Long:
540
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
541
case BuiltinTypeSpec.Type.Float:
542
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
543
case BuiltinTypeSpec.Type.Double:
544
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
545
case BuiltinTypeSpec.Type.Decimal:
546
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
549
case BuiltinTypeSpec.Type.Short:
551
// From short to int, long, float, double, decimal
553
switch (target_type.BuiltinType) {
554
case BuiltinTypeSpec.Type.Int:
555
return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
556
case BuiltinTypeSpec.Type.Long:
557
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
558
case BuiltinTypeSpec.Type.Double:
559
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
560
case BuiltinTypeSpec.Type.Float:
561
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
562
case BuiltinTypeSpec.Type.Decimal:
563
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
566
case BuiltinTypeSpec.Type.UShort:
568
// From ushort to int, uint, long, ulong, float, double, decimal
570
switch (target_type.BuiltinType) {
571
case BuiltinTypeSpec.Type.Int:
572
case BuiltinTypeSpec.Type.UInt:
573
return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
574
case BuiltinTypeSpec.Type.ULong:
575
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
576
case BuiltinTypeSpec.Type.Long:
577
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
578
case BuiltinTypeSpec.Type.Double:
579
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
580
case BuiltinTypeSpec.Type.Float:
581
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
582
case BuiltinTypeSpec.Type.Decimal:
583
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
586
case BuiltinTypeSpec.Type.Int:
588
// From int to long, float, double, decimal
590
switch (target_type.BuiltinType) {
591
case BuiltinTypeSpec.Type.Long:
592
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
593
case BuiltinTypeSpec.Type.Double:
594
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
595
case BuiltinTypeSpec.Type.Float:
596
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
597
case BuiltinTypeSpec.Type.Decimal:
598
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
601
case BuiltinTypeSpec.Type.UInt:
603
// From uint to long, ulong, float, double, decimal
605
switch (target_type.BuiltinType) {
606
case BuiltinTypeSpec.Type.Long:
607
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
608
case BuiltinTypeSpec.Type.ULong:
609
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
610
case BuiltinTypeSpec.Type.Double:
611
return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
612
case BuiltinTypeSpec.Type.Float:
613
return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
614
case BuiltinTypeSpec.Type.Decimal:
615
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
618
case BuiltinTypeSpec.Type.Long:
620
// From long to float, double, decimal
622
switch (target_type.BuiltinType) {
623
case BuiltinTypeSpec.Type.Double:
624
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
625
case BuiltinTypeSpec.Type.Float:
626
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
627
case BuiltinTypeSpec.Type.Decimal:
628
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
631
case BuiltinTypeSpec.Type.ULong:
633
// From ulong to float, double, decimal
635
switch (target_type.BuiltinType) {
636
case BuiltinTypeSpec.Type.Double:
637
return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
638
case BuiltinTypeSpec.Type.Float:
639
return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
640
case BuiltinTypeSpec.Type.Decimal:
641
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
644
case BuiltinTypeSpec.Type.Char:
646
// From char to ushort, int, uint, long, ulong, float, double, decimal
648
switch (target_type.BuiltinType) {
649
case BuiltinTypeSpec.Type.UShort:
650
case BuiltinTypeSpec.Type.Int:
651
case BuiltinTypeSpec.Type.UInt:
652
return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
653
case BuiltinTypeSpec.Type.ULong:
654
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
655
case BuiltinTypeSpec.Type.Long:
656
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
657
case BuiltinTypeSpec.Type.Float:
658
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
659
case BuiltinTypeSpec.Type.Double:
660
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
661
case BuiltinTypeSpec.Type.Decimal:
662
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
665
case BuiltinTypeSpec.Type.Float:
669
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
670
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
678
// Full version of implicit conversion
680
public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type)
682
if (ImplicitStandardConversionExists (expr, target_type))
685
if (expr.Type == InternalType.AnonymousMethod) {
686
if (!target_type.IsDelegate && !target_type.IsExpressionTreeType)
689
AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
690
return ame.ImplicitStandardConversionExists (ec, target_type);
693
if (expr.eclass == ExprClass.MethodGroup) {
694
if (target_type.IsDelegate && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) {
695
MethodGroupExpr mg = expr as MethodGroupExpr;
697
return DelegateCreation.ImplicitStandardConversionExists (ec, mg, target_type);
703
// Conversion from __arglist to System.ArgIterator
704
if (expr.Type == InternalType.Arglist)
705
return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec;
707
return UserDefinedConversion (ec, expr, target_type, true, true, Location.Null) != null;
711
// Implicit standard conversion (only core conversions are used here)
713
public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type)
716
// Identity conversions
717
// Implicit numeric conversions
718
// Implicit nullable conversions
719
// Implicit reference conversions
720
// Boxing conversions
721
// Implicit constant expression conversions
722
// Implicit conversions involving type parameters
725
TypeSpec expr_type = expr.Type;
727
if (expr_type == target_type)
730
if (target_type.IsNullableType)
731
return ImplicitNulableConversion (null, expr, target_type) != null;
733
if (ImplicitNumericConversion (null, expr_type, target_type) != null)
736
if (ImplicitReferenceConversionExists (expr_type, target_type, false))
739
if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
743
// Implicit Constant Expression Conversions
745
if (expr is IntConstant){
746
int value = ((IntConstant) expr).Value;
747
switch (target_type.BuiltinType) {
748
case BuiltinTypeSpec.Type.SByte:
749
if (value >= SByte.MinValue && value <= SByte.MaxValue)
752
case BuiltinTypeSpec.Type.Byte:
753
if (value >= 0 && value <= Byte.MaxValue)
756
case BuiltinTypeSpec.Type.Short:
757
if (value >= Int16.MinValue && value <= Int16.MaxValue)
760
case BuiltinTypeSpec.Type.UShort:
761
if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
764
case BuiltinTypeSpec.Type.UInt:
768
case BuiltinTypeSpec.Type.ULong:
770
// we can optimize this case: a positive int32
771
// always fits on a uint64. But we need an opcode
781
if (expr is LongConstant && target_type.BuiltinType == BuiltinTypeSpec.Type.ULong){
783
// Try the implicit constant expression conversion
784
// from long to ulong, instead of a nice routine,
787
long v = ((LongConstant) expr).Value;
792
if (expr is IntegralConstant && target_type.IsEnum) {
793
var i = (IntegralConstant) expr;
795
// LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
797
// An implicit enumeration conversion permits the decimal-integer-literal 0
798
// to be converted to any enum-type and to any nullable-type whose underlying
799
// type is an enum-type
801
return i.IsZeroInteger;
805
// Implicit dynamic conversion for remaining value types. It should probably
808
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
809
switch (target_type.Kind) {
810
case MemberKind.Struct:
811
case MemberKind.Enum:
819
// In an unsafe context implicit conversions is extended to include
821
// From any pointer-type to the type void*
822
// From the null literal to any pointer-type.
824
// LAMESPEC: The specification claims this conversion is allowed in implicit conversion but
825
// in reality implicit standard conversion uses it
827
if (target_type.IsPointer && expr.Type.IsPointer && ((PointerContainer) target_type).Element.Kind == MemberKind.Void)
831
// Struct identity conversion, including dynamic erasure
833
if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
840
/// Finds "most encompassed type" according to the spec (13.4.2)
841
/// amongst the methods in the MethodGroupExpr
843
public static TypeSpec FindMostEncompassedType (IList<TypeSpec> types)
845
TypeSpec best = null;
846
EmptyExpression expr;
848
foreach (TypeSpec t in types) {
854
expr = new EmptyExpression (t);
855
if (ImplicitStandardConversionExists (expr, best))
859
expr = new EmptyExpression (best);
860
foreach (TypeSpec t in types) {
863
if (!ImplicitStandardConversionExists (expr, t)) {
873
// Finds the most encompassing type (type into which all other
874
// types can convert to) amongst the types in the given set
876
static TypeSpec FindMostEncompassingType (IList<TypeSpec> types)
878
if (types.Count == 0)
881
if (types.Count == 1)
884
TypeSpec best = null;
885
for (int i = 0; i < types.Count; ++i) {
887
for (; ii < types.Count; ++ii) {
891
var expr = new EmptyExpression (types[ii]);
892
if (!ImplicitStandardConversionExists (expr, types [i])) {
906
// Indicates multiple best types
907
return InternalType.FakeInternalType;
914
// Finds the most specific source Sx according to the rules of the spec (13.4.4)
915
// by making use of FindMostEncomp* methods. Applies the correct rules separately
916
// for explicit and implicit conversion operators.
918
static TypeSpec FindMostSpecificSource (List<MethodSpec> list, TypeSpec sourceType, Expression source, bool apply_explicit_conv_rules)
920
TypeSpec[] src_types_set = null;
923
// Try exact match first, if any operator converts from S then Sx = S
925
for (int i = 0; i < list.Count; ++i) {
926
TypeSpec param_type = list [i].Parameters.Types [0];
928
if (param_type == sourceType)
931
if (src_types_set == null)
932
src_types_set = new TypeSpec [list.Count];
934
src_types_set [i] = param_type;
938
// Explicit Conv rules
940
if (apply_explicit_conv_rules) {
941
var candidate_set = new List<TypeSpec> ();
943
foreach (TypeSpec param_type in src_types_set){
944
if (ImplicitStandardConversionExists (source, param_type))
945
candidate_set.Add (param_type);
948
if (candidate_set.Count != 0)
949
return FindMostEncompassedType (candidate_set);
955
if (apply_explicit_conv_rules)
956
return FindMostEncompassingType (src_types_set);
958
return FindMostEncompassedType (src_types_set);
962
/// Finds the most specific target Tx according to section 13.4.4
964
static public TypeSpec FindMostSpecificTarget (IList<MethodSpec> list,
965
TypeSpec target, bool apply_explicit_conv_rules)
967
List<TypeSpec> tgt_types_set = null;
970
// If any operator converts to T then Tx = T
972
foreach (var mi in list){
973
TypeSpec ret_type = mi.ReturnType;
974
if (ret_type == target)
977
if (tgt_types_set == null) {
978
tgt_types_set = new List<TypeSpec> (list.Count);
979
} else if (tgt_types_set.Contains (ret_type)) {
983
tgt_types_set.Add (ret_type);
987
// Explicit conv rules
989
if (apply_explicit_conv_rules) {
990
var candidate_set = new List<TypeSpec> ();
992
foreach (TypeSpec ret_type in tgt_types_set) {
993
var expr = new EmptyExpression (ret_type);
995
if (ImplicitStandardConversionExists (expr, target))
996
candidate_set.Add (ret_type);
999
if (candidate_set.Count != 0)
1000
return FindMostEncompassingType (candidate_set);
1004
// Okay, final case !
1006
if (apply_explicit_conv_rules)
1007
return FindMostEncompassedType (tgt_types_set);
1009
return FindMostEncompassingType (tgt_types_set);
1013
/// User-defined Implicit conversions
1015
static public Expression ImplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
1017
return UserDefinedConversion (ec, source, target, true, false, loc);
1021
/// User-defined Explicit conversions
1023
static Expression ExplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
1025
return UserDefinedConversion (ec, source, target, false, false, loc);
1028
static void FindApplicableUserDefinedConversionOperators (IList<MemberSpec> operators, Expression source, TypeSpec target, bool implicitOnly, ref List<MethodSpec> candidates)
1030
if (source.Type.IsInterface) {
1031
// Neither A nor B are interface-types
1035
// For a conversion operator to be applicable, it must be possible
1036
// to perform a standard conversion from the source type to
1037
// the operand type of the operator, and it must be possible
1038
// to perform a standard conversion from the result type of
1039
// the operator to the target type.
1041
Expression texpr = null;
1043
foreach (MethodSpec op in operators) {
1045
// Can be null because MemberCache.GetUserOperator does not resize the array
1049
var t = op.Parameters.Types[0];
1050
if (source.Type != t && !ImplicitStandardConversionExists (source, t)) {
1054
if (!ImplicitStandardConversionExists (new EmptyExpression (t), source.Type))
1064
if (t.IsNullableType)
1065
t = Nullable.NullableInfo.GetUnderlyingType (t);
1067
if (!ImplicitStandardConversionExists (new EmptyExpression (t), target)) {
1072
texpr = new EmptyExpression (target);
1074
if (!ImplicitStandardConversionExists (texpr, t))
1079
if (candidates == null)
1080
candidates = new List<MethodSpec> ();
1082
candidates.Add (op);
1087
// User-defined conversions
1089
static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, bool probingOnly, Location loc)
1091
List<MethodSpec> candidates = null;
1094
// If S or T are nullable types, source_type and target_type are their underlying types
1095
// otherwise source_type and target_type are equal to S and T respectively.
1097
TypeSpec source_type = source.Type;
1098
TypeSpec target_type = target;
1099
Expression source_type_expr;
1101
if (source_type.IsNullableType) {
1102
// No unwrapping conversion S? -> T for non-reference types
1103
if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) {
1104
source_type_expr = source;
1106
source_type_expr = Nullable.Unwrap.Create (source);
1107
source_type = source_type_expr.Type;
1110
source_type_expr = source;
1113
if (target_type.IsNullableType)
1114
target_type = Nullable.NullableInfo.GetUnderlyingType (target_type);
1116
// Only these containers can contain a user defined implicit or explicit operators
1117
const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter;
1119
if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1120
bool declared_only = source_type.IsStruct;
1122
var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only);
1123
if (operators != null) {
1124
FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1127
if (!implicitOnly) {
1128
operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only);
1129
if (operators != null) {
1130
FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1135
if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1136
bool declared_only = target.IsStruct || implicitOnly;
1138
var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only);
1139
if (operators != null) {
1140
FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1143
if (!implicitOnly) {
1144
operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only);
1145
if (operators != null) {
1146
FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1151
if (candidates == null)
1155
// Find the most specific conversion operator
1157
MethodSpec most_specific_operator;
1159
if (candidates.Count == 1) {
1160
most_specific_operator = candidates[0];
1161
s_x = most_specific_operator.Parameters.Types[0];
1162
t_x = most_specific_operator.ReturnType;
1165
// Pass original source type to find the best match against input type and
1166
// not the unwrapped expression
1168
s_x = FindMostSpecificSource (candidates, source.Type, source_type_expr, !implicitOnly);
1172
t_x = FindMostSpecificTarget (candidates, target, !implicitOnly);
1176
most_specific_operator = null;
1177
for (int i = 0; i < candidates.Count; ++i) {
1178
if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) {
1179
most_specific_operator = candidates[i];
1184
if (most_specific_operator == null) {
1186
// Unless running in probing more
1189
MethodSpec ambig_arg = null;
1190
foreach (var candidate in candidates) {
1191
if (candidate.ReturnType == t_x)
1192
most_specific_operator = candidate;
1193
else if (candidate.Parameters.Types[0] == s_x)
1194
ambig_arg = candidate;
1197
ec.Report.Error (457, loc,
1198
"Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'",
1199
ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (),
1200
source.Type.GetSignatureForError (), target.GetSignatureForError ());
1203
return ErrorExpression.Instance;
1208
// Convert input type when it's different to best operator argument
1210
if (s_x != source_type) {
1211
var c = source as Constant;
1213
source = c.Reduce (ec, s_x);
1219
source = implicitOnly ?
1220
ImplicitConversionStandard (ec, source_type_expr, s_x, loc) :
1221
ExplicitConversionStandard (ec, source_type_expr, s_x, loc);
1224
source = source_type_expr;
1227
source = new UserCast (most_specific_operator, source, loc).Resolve (ec);
1230
// Convert result type when it's different to best operator return type
1232
if (t_x != target_type) {
1234
// User operator is of T?, no need to lift it
1236
if (t_x == target && t_x.IsNullableType)
1239
source = implicitOnly ?
1240
ImplicitConversionStandard (ec, source, target_type, loc) :
1241
ExplicitConversionStandard (ec, source, target_type, loc);
1248
// Source expression is of nullable type, lift the result in the case it's null and
1249
// not nullable/lifted user operator is used
1251
if (source_type_expr is Nullable.Unwrap && !s_x.IsNullableType && (TypeSpec.IsReferenceType (target) || target_type != target))
1252
source = new Nullable.Lifted (source, source_type_expr, target).Resolve (ec);
1253
else if (target_type != target)
1254
source = Nullable.Wrap.Create (source, target);
1260
/// Converts implicitly the resolved expression `expr' into the
1261
/// `target_type'. It returns a new expression that can be used
1262
/// in a context that expects a `target_type'.
1264
static public Expression ImplicitConversion (ResolveContext ec, Expression expr,
1265
TypeSpec target_type, Location loc)
1269
if (target_type == null)
1270
throw new Exception ("Target type is null");
1272
e = ImplicitConversionStandard (ec, expr, target_type, loc);
1276
e = ImplicitUserConversion (ec, expr, target_type, loc);
1285
/// Attempts to apply the `Standard Implicit
1286
/// Conversion' rules to the expression `expr' into
1287
/// the `target_type'. It returns a new expression
1288
/// that can be used in a context that expects a
1291
/// This is different from `ImplicitConversion' in that the
1292
/// user defined implicit conversions are excluded.
1294
static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr,
1295
TypeSpec target_type, Location loc)
1297
return ImplicitConversionStandard (ec, expr, target_type, loc, false);
1300
static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast)
1302
if (expr.eclass == ExprClass.MethodGroup){
1303
if (!target_type.IsDelegate){
1308
// Only allow anonymous method conversions on post ISO_1
1310
if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){
1311
MethodGroupExpr mg = expr as MethodGroupExpr;
1313
return new ImplicitDelegateCreation (target_type, mg, loc).Resolve (ec);
1317
TypeSpec expr_type = expr.Type;
1320
if (expr_type == target_type) {
1321
if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod)
1326
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1327
switch (target_type.Kind) {
1328
case MemberKind.ArrayType:
1329
case MemberKind.Class:
1330
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object)
1331
return EmptyCast.Create (expr, target_type);
1333
goto case MemberKind.Struct;
1334
case MemberKind.Struct:
1335
case MemberKind.Delegate:
1336
case MemberKind.Enum:
1337
case MemberKind.Interface:
1338
case MemberKind.TypeParameter:
1339
Arguments args = new Arguments (1);
1340
args.Add (new Argument (expr));
1341
return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec);
1347
if (target_type.IsNullableType)
1348
return ImplicitNulableConversion (ec, expr, target_type);
1351
// Attempt to do the implicit constant expression conversions
1353
Constant c = expr as Constant;
1356
c = c.ConvertImplicitly (target_type);
1358
throw new InternalErrorException ("Conversion error", loc);
1364
e = ImplicitNumericConversion (expr, expr_type, target_type);
1368
e = ImplicitReferenceConversion (expr, target_type, explicit_cast);
1372
e = ImplicitBoxingConversion (expr, expr_type, target_type);
1376
if (expr is IntegralConstant && target_type.IsEnum){
1377
var i = (IntegralConstant) expr;
1379
// LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
1381
// An implicit enumeration conversion permits the decimal-integer-literal 0
1382
// to be converted to any enum-type and to any nullable-type whose underlying
1383
// type is an enum-type
1385
if (i.IsZeroInteger) {
1386
// Recreate 0 literal to remove any collected conversions
1387
return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type);
1392
var target_pc = target_type as PointerContainer;
1393
if (target_pc != null) {
1394
if (expr_type.IsPointer) {
1396
// Pointer types are same when they have same element types
1398
if (expr_type == target_pc)
1401
if (target_pc.Element.Kind == MemberKind.Void)
1402
return EmptyCast.Create (expr, target_type);
1407
if (expr_type == InternalType.NullLiteral)
1408
return new NullPointer (target_type, loc);
1412
if (expr_type == InternalType.AnonymousMethod){
1413
AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
1414
Expression am = ame.Compatible (ec, target_type);
1416
return am.Resolve (ec);
1419
if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec)
1423
// dynamic erasure conversion on value types
1425
if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
1426
return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type);
1432
/// Attempts to implicitly convert `source' into `target_type', using
1433
/// ImplicitConversion. If there is no implicit conversion, then
1434
/// an error is signaled
1436
static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
1437
TypeSpec target_type, Location loc)
1439
Expression e = ImplicitConversion (ec, source, target_type, loc);
1443
source.Error_ValueCannotBeConverted (ec, target_type, false);
1448
/// Performs the explicit numeric conversions
1450
/// There are a few conversions that are not part of the C# standard,
1451
/// they were interim hacks in the C# compiler that were supposed to
1452
/// become explicit operators in the UIntPtr class and IntPtr class,
1453
/// but for historical reasons it did not happen, so the C# compiler
1454
/// ended up with these special hacks.
1456
/// See bug 59800 for details.
1458
/// The conversion are:
1468
public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type)
1470
// Not all predefined explicit numeric conversion are
1471
// defined here, for some of them (mostly IntPtr/UIntPtr) we
1472
// defer to user-operator handling which is now perfect but
1475
// LAMESPEC: Undocumented IntPtr/UIntPtr conversions
1476
// IntPtr -> uint uses int
1477
// UIntPtr -> long uses ulong
1480
switch (expr.Type.BuiltinType) {
1481
case BuiltinTypeSpec.Type.SByte:
1483
// From sbyte to byte, ushort, uint, ulong, char, uintptr
1485
switch (target_type.BuiltinType) {
1486
case BuiltinTypeSpec.Type.Byte:
1487
return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
1488
case BuiltinTypeSpec.Type.UShort:
1489
return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
1490
case BuiltinTypeSpec.Type.UInt:
1491
return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
1492
case BuiltinTypeSpec.Type.ULong:
1493
return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
1494
case BuiltinTypeSpec.Type.Char:
1495
return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
1497
// One of the built-in conversions that belonged in the class library
1498
case BuiltinTypeSpec.Type.UIntPtr:
1499
return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true);
1502
case BuiltinTypeSpec.Type.Byte:
1504
// From byte to sbyte and char
1506
switch (target_type.BuiltinType) {
1507
case BuiltinTypeSpec.Type.SByte:
1508
return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
1509
case BuiltinTypeSpec.Type.Char:
1510
return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
1513
case BuiltinTypeSpec.Type.Short:
1515
// From short to sbyte, byte, ushort, uint, ulong, char, uintptr
1517
switch (target_type.BuiltinType) {
1518
case BuiltinTypeSpec.Type.SByte:
1519
return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
1520
case BuiltinTypeSpec.Type.Byte:
1521
return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
1522
case BuiltinTypeSpec.Type.UShort:
1523
return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
1524
case BuiltinTypeSpec.Type.UInt:
1525
return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
1526
case BuiltinTypeSpec.Type.ULong:
1527
return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
1528
case BuiltinTypeSpec.Type.Char:
1529
return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
1531
// One of the built-in conversions that belonged in the class library
1532
case BuiltinTypeSpec.Type.UIntPtr:
1533
return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1536
case BuiltinTypeSpec.Type.UShort:
1538
// From ushort to sbyte, byte, short, char
1540
switch (target_type.BuiltinType) {
1541
case BuiltinTypeSpec.Type.SByte:
1542
return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
1543
case BuiltinTypeSpec.Type.Byte:
1544
return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
1545
case BuiltinTypeSpec.Type.Short:
1546
return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
1547
case BuiltinTypeSpec.Type.Char:
1548
return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
1551
case BuiltinTypeSpec.Type.Int:
1553
// From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
1555
switch (target_type.BuiltinType) {
1556
case BuiltinTypeSpec.Type.SByte:
1557
return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
1558
case BuiltinTypeSpec.Type.Byte:
1559
return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
1560
case BuiltinTypeSpec.Type.Short:
1561
return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
1562
case BuiltinTypeSpec.Type.UShort:
1563
return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
1564
case BuiltinTypeSpec.Type.UInt:
1565
return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
1566
case BuiltinTypeSpec.Type.ULong:
1567
return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
1568
case BuiltinTypeSpec.Type.Char:
1569
return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
1571
// One of the built-in conversions that belonged in the class library
1572
case BuiltinTypeSpec.Type.UIntPtr:
1573
return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1576
case BuiltinTypeSpec.Type.UInt:
1578
// From uint to sbyte, byte, short, ushort, int, char
1580
switch (target_type.BuiltinType) {
1581
case BuiltinTypeSpec.Type.SByte:
1582
return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
1583
case BuiltinTypeSpec.Type.Byte:
1584
return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
1585
case BuiltinTypeSpec.Type.Short:
1586
return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
1587
case BuiltinTypeSpec.Type.UShort:
1588
return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
1589
case BuiltinTypeSpec.Type.Int:
1590
return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
1591
case BuiltinTypeSpec.Type.Char:
1592
return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
1595
case BuiltinTypeSpec.Type.Long:
1597
// From long to sbyte, byte, short, ushort, int, uint, ulong, char
1599
switch (target_type.BuiltinType) {
1600
case BuiltinTypeSpec.Type.SByte:
1601
return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
1602
case BuiltinTypeSpec.Type.Byte:
1603
return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
1604
case BuiltinTypeSpec.Type.Short:
1605
return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
1606
case BuiltinTypeSpec.Type.UShort:
1607
return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
1608
case BuiltinTypeSpec.Type.Int:
1609
return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
1610
case BuiltinTypeSpec.Type.UInt:
1611
return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
1612
case BuiltinTypeSpec.Type.ULong:
1613
return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
1614
case BuiltinTypeSpec.Type.Char:
1615
return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
1618
case BuiltinTypeSpec.Type.ULong:
1620
// From ulong to sbyte, byte, short, ushort, int, uint, long, char
1622
switch (target_type.BuiltinType) {
1623
case BuiltinTypeSpec.Type.SByte:
1624
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
1625
case BuiltinTypeSpec.Type.Byte:
1626
return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
1627
case BuiltinTypeSpec.Type.Short:
1628
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
1629
case BuiltinTypeSpec.Type.UShort:
1630
return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
1631
case BuiltinTypeSpec.Type.Int:
1632
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
1633
case BuiltinTypeSpec.Type.UInt:
1634
return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
1635
case BuiltinTypeSpec.Type.Long:
1636
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
1637
case BuiltinTypeSpec.Type.Char:
1638
return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
1640
// One of the built-in conversions that belonged in the class library
1641
case BuiltinTypeSpec.Type.IntPtr:
1642
return new OperatorCast (EmptyCast.Create (expr, rc.BuiltinTypes.Long), target_type, true);
1645
case BuiltinTypeSpec.Type.Char:
1647
// From char to sbyte, byte, short
1649
switch (target_type.BuiltinType) {
1650
case BuiltinTypeSpec.Type.SByte:
1651
return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
1652
case BuiltinTypeSpec.Type.Byte:
1653
return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
1654
case BuiltinTypeSpec.Type.Short:
1655
return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
1658
case BuiltinTypeSpec.Type.Float:
1660
// From float to sbyte, byte, short,
1661
// ushort, int, uint, long, ulong, char
1664
switch (target_type.BuiltinType) {
1665
case BuiltinTypeSpec.Type.SByte:
1666
return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
1667
case BuiltinTypeSpec.Type.Byte:
1668
return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
1669
case BuiltinTypeSpec.Type.Short:
1670
return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
1671
case BuiltinTypeSpec.Type.UShort:
1672
return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
1673
case BuiltinTypeSpec.Type.Int:
1674
return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
1675
case BuiltinTypeSpec.Type.UInt:
1676
return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
1677
case BuiltinTypeSpec.Type.Long:
1678
return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
1679
case BuiltinTypeSpec.Type.ULong:
1680
return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
1681
case BuiltinTypeSpec.Type.Char:
1682
return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
1683
case BuiltinTypeSpec.Type.Decimal:
1684
return new OperatorCast (expr, target_type, true);
1687
case BuiltinTypeSpec.Type.Double:
1689
// From double to sbyte, byte, short,
1690
// ushort, int, uint, long, ulong,
1691
// char, float or decimal
1693
switch (target_type.BuiltinType) {
1694
case BuiltinTypeSpec.Type.SByte:
1695
return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
1696
case BuiltinTypeSpec.Type.Byte:
1697
return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
1698
case BuiltinTypeSpec.Type.Short:
1699
return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
1700
case BuiltinTypeSpec.Type.UShort:
1701
return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
1702
case BuiltinTypeSpec.Type.Int:
1703
return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
1704
case BuiltinTypeSpec.Type.UInt:
1705
return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
1706
case BuiltinTypeSpec.Type.Long:
1707
return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
1708
case BuiltinTypeSpec.Type.ULong:
1709
return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
1710
case BuiltinTypeSpec.Type.Char:
1711
return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
1712
case BuiltinTypeSpec.Type.Float:
1713
return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
1714
case BuiltinTypeSpec.Type.Decimal:
1715
return new OperatorCast (expr, target_type, true);
1718
case BuiltinTypeSpec.Type.UIntPtr:
1720
// Various built-in conversions that belonged in the class library
1722
// from uintptr to sbyte, short, int32
1724
switch (target_type.BuiltinType) {
1725
case BuiltinTypeSpec.Type.SByte:
1726
return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I1);
1727
case BuiltinTypeSpec.Type.Short:
1728
return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I2);
1729
case BuiltinTypeSpec.Type.Int:
1730
return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type);
1731
case BuiltinTypeSpec.Type.UInt:
1732
return new OperatorCast (expr, expr.Type, target_type, true);
1733
case BuiltinTypeSpec.Type.Long:
1734
return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.ULong, true), target_type);
1737
case BuiltinTypeSpec.Type.IntPtr:
1738
if (target_type.BuiltinType == BuiltinTypeSpec.Type.UInt)
1739
return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Int, true), target_type);
1740
if (target_type.BuiltinType == BuiltinTypeSpec.Type.ULong)
1741
return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Long, true), target_type);
1744
case BuiltinTypeSpec.Type.Decimal:
1745
// From decimal to sbyte, byte, short,
1746
// ushort, int, uint, long, ulong, char,
1748
switch (target_type.BuiltinType) {
1749
case BuiltinTypeSpec.Type.SByte:
1750
case BuiltinTypeSpec.Type.Byte:
1751
case BuiltinTypeSpec.Type.Short:
1752
case BuiltinTypeSpec.Type.UShort:
1753
case BuiltinTypeSpec.Type.Int:
1754
case BuiltinTypeSpec.Type.UInt:
1755
case BuiltinTypeSpec.Type.Long:
1756
case BuiltinTypeSpec.Type.ULong:
1757
case BuiltinTypeSpec.Type.Char:
1758
case BuiltinTypeSpec.Type.Float:
1759
case BuiltinTypeSpec.Type.Double:
1760
return new OperatorCast (expr, expr.Type, target_type, true);
1770
/// Returns whether an explicit reference conversion can be performed
1771
/// from source_type to target_type
1773
public static bool ExplicitReferenceConversionExists (TypeSpec source_type, TypeSpec target_type)
1775
Expression e = ExplicitReferenceConversion (null, source_type, target_type);
1779
if (e == EmptyExpression.Null)
1782
throw new InternalErrorException ("Invalid probing conversion result");
1786
/// Implements Explicit Reference conversions
1788
static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
1791
// From object to a generic parameter
1793
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type))
1794
return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1797
// Explicit type parameter conversion.
1799
if (source_type.Kind == MemberKind.TypeParameter)
1800
return ExplicitTypeParameterConversion (source, source_type, target_type);
1802
bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum;
1805
// Unboxing conversion from System.ValueType to any non-nullable-value-type
1807
if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type)
1808
return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1811
// From object or dynamic to any reference type or value type (unboxing)
1813
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1814
if (target_type.IsPointer)
1818
source == null ? EmptyExpression.Null :
1819
target_is_value_type ? new UnboxCast (source, target_type) :
1820
source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) :
1821
new ClassCast (source, target_type);
1825
// From any class S to any class-type T, provided S is a base class of T
1827
if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true))
1828
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1831
// From any interface-type S to to any class type T, provided T is not
1832
// sealed, or provided T implements S.
1834
if (source_type.Kind == MemberKind.Interface) {
1835
if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) {
1837
return EmptyExpression.Null;
1840
// Unboxing conversion from any interface-type to any non-nullable-value-type that
1841
// implements the interface-type
1843
return target_is_value_type ? new UnboxCast (source, target_type) : (Expression) new ClassCast (source, target_type);
1847
// From System.Collections.Generic.IList<T> and its base interfaces to a one-dimensional
1848
// array type S[], provided there is an implicit or explicit reference conversion from S to T.
1850
var target_array = target_type as ArrayContainer;
1851
if (target_array != null && IList_To_Array (source_type, target_array))
1852
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1857
var source_array = source_type as ArrayContainer;
1858
if (source_array != null) {
1859
var target_array = target_type as ArrayContainer;
1860
if (target_array != null) {
1862
// From System.Array to any array-type
1864
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array)
1865
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1868
// From an array type S with an element type Se to an array type T with an
1869
// element type Te provided all the following are true:
1870
// * S and T differe only in element type, in other words, S and T
1871
// have the same number of dimensions.
1872
// * Both Se and Te are reference types
1873
// * An explicit reference conversions exist from Se to Te
1875
if (source_array.Rank == target_array.Rank) {
1877
source_type = source_array.Element;
1878
if (!TypeSpec.IsReferenceType (source_type))
1881
var target_element = target_array.Element;
1882
if (!TypeSpec.IsReferenceType (target_element))
1885
if (ExplicitReferenceConversionExists (source_type, target_element))
1886
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1893
// From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces,
1894
// provided that there is an explicit reference conversion from S to T
1896
if (ArrayToIList (source_array, target_type, true))
1897
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1903
// From any class type S to any interface T, provides S is not sealed
1904
// and provided S does not implement T.
1906
if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type, true)) {
1907
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1911
// From System delegate to any delegate-type
1913
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && target_type.IsDelegate)
1914
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1917
// From variant generic delegate to same variant generic delegate type
1919
if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) {
1920
var tparams = source_type.MemberDefinition.TypeParameters;
1921
var targs_src = source_type.TypeArguments;
1922
var targs_dst = target_type.TypeArguments;
1924
for (i = 0; i < tparams.Length; ++i) {
1926
// If TP is invariant, types have to be identical
1928
if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i]))
1931
if (tparams[i].Variance == Variance.Covariant) {
1933
//If TP is covariant, an implicit or explicit identity or reference conversion is required
1935
if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1938
if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1941
} else if (tparams[i].Variance == Variance.Contravariant) {
1943
//If TP is contravariant, both are either identical or reference types
1945
if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i]))
1952
if (i == tparams.Length)
1953
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1960
/// Performs an explicit conversion of the expression `expr' whose
1961
/// type is expr.Type to `target_type'.
1963
static public Expression ExplicitConversionCore (ResolveContext ec, Expression expr,
1964
TypeSpec target_type, Location loc)
1966
TypeSpec expr_type = expr.Type;
1968
// Explicit conversion includes implicit conversion and it used for enum underlying types too
1969
Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true);
1973
if (expr_type.IsEnum) {
1974
TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1975
Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type));
1976
if (underlying.Type == real_target)
1980
ne = ImplicitNumericConversion (underlying, real_target);
1983
ne = ExplicitNumericConversion (ec, underlying, real_target);
1986
// LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
1988
if (ne == null && (real_target.BuiltinType == BuiltinTypeSpec.Type.IntPtr || real_target.BuiltinType == BuiltinTypeSpec.Type.UIntPtr))
1989
ne = ExplicitUserConversion (ec, underlying, real_target, loc);
1991
return ne != null ? EmptyCast.Create (ne, target_type) : null;
1994
if (target_type.IsEnum) {
1996
// System.Enum can be unboxed to any enum-type
1998
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Enum)
1999
return new UnboxCast (expr, target_type);
2001
TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
2003
if (expr_type == real_target)
2004
return EmptyCast.Create (expr, target_type);
2006
Constant c = expr as Constant;
2008
c = c.TryReduce (ec, real_target);
2012
ne = ImplicitNumericConversion (expr, real_target);
2014
return EmptyCast.Create (ne, target_type);
2016
ne = ExplicitNumericConversion (ec, expr, real_target);
2018
return EmptyCast.Create (ne, target_type);
2021
// LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
2023
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.IntPtr || expr_type.BuiltinType == BuiltinTypeSpec.Type.UIntPtr) {
2024
ne = ExplicitUserConversion (ec, expr, real_target, loc);
2026
return ExplicitConversionCore (ec, ne, target_type, loc);
2030
ne = ExplicitNumericConversion (ec, expr, target_type);
2036
// Skip the ExplicitReferenceConversion because we can not convert
2037
// from Null to a ValueType, and ExplicitReference wont check against
2038
// null literal explicitly
2040
if (expr_type != InternalType.NullLiteral) {
2041
ne = ExplicitReferenceConversion (expr, expr_type, target_type);
2047
ne = ExplicitUnsafe (expr, target_type);
2055
public static Expression ExplicitUnsafe (Expression expr, TypeSpec target_type)
2057
TypeSpec expr_type = expr.Type;
2059
if (target_type.IsPointer){
2060
if (expr_type.IsPointer)
2061
return EmptyCast.Create (expr, target_type);
2063
switch (expr_type.BuiltinType) {
2064
case BuiltinTypeSpec.Type.SByte:
2065
case BuiltinTypeSpec.Type.Short:
2066
case BuiltinTypeSpec.Type.Int:
2067
return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
2069
case BuiltinTypeSpec.Type.UShort:
2070
case BuiltinTypeSpec.Type.UInt:
2071
case BuiltinTypeSpec.Type.Byte:
2072
return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2074
case BuiltinTypeSpec.Type.Long:
2075
return new ConvCast (expr, target_type, ConvCast.Mode.I8_I);
2077
case BuiltinTypeSpec.Type.ULong:
2078
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I);
2082
if (expr_type.IsPointer){
2083
switch (target_type.BuiltinType) {
2084
case BuiltinTypeSpec.Type.SByte:
2085
return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
2086
case BuiltinTypeSpec.Type.Byte:
2087
return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
2088
case BuiltinTypeSpec.Type.Short:
2089
return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
2090
case BuiltinTypeSpec.Type.UShort:
2091
return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
2092
case BuiltinTypeSpec.Type.Int:
2093
return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
2094
case BuiltinTypeSpec.Type.UInt:
2095
return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
2096
case BuiltinTypeSpec.Type.Long:
2097
return new ConvCast (expr, target_type, ConvCast.Mode.I_I8);
2098
case BuiltinTypeSpec.Type.ULong:
2099
return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
2106
/// Same as ExplicitConversion, only it doesn't include user defined conversions
2108
static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr,
2109
TypeSpec target_type, Location l)
2111
int errors = ec.Report.Errors;
2112
Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
2113
if (ec.Report.Errors > errors)
2119
ne = ExplicitNumericConversion (ec, expr, target_type);
2123
ne = ExplicitReferenceConversion (expr, expr.Type, target_type);
2127
if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void)
2128
return EmptyCast.Create (expr, target_type);
2130
expr.Error_ValueCannotBeConverted (ec, target_type, true);
2135
/// Performs an explicit conversion of the expression `expr' whose
2136
/// type is expr.Type to `target_type'.
2138
static public Expression ExplicitConversion (ResolveContext ec, Expression expr,
2139
TypeSpec target_type, Location loc)
2141
Expression e = ExplicitConversionCore (ec, expr, target_type, loc);
2144
// Don't eliminate explicit precission casts
2147
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float)
2148
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
2150
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
2151
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
2157
TypeSpec expr_type = expr.Type;
2158
if (target_type.IsNullableType) {
2161
if (expr_type.IsNullableType) {
2162
target = Nullable.NullableInfo.GetUnderlyingType (target_type);
2163
Expression unwrap = Nullable.Unwrap.Create (expr);
2164
e = ExplicitConversion (ec, unwrap, target, expr.Location);
2168
return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec);
2170
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2171
return new UnboxCast (expr, target_type);
2174
target = TypeManager.GetTypeArguments (target_type) [0];
2175
e = ExplicitConversionCore (ec, expr, target, loc);
2177
return Nullable.Wrap.Create (e, target_type);
2178
} else if (expr_type.IsNullableType) {
2179
e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
2183
e = Nullable.Unwrap.Create (expr, false);
2184
e = ExplicitConversionCore (ec, e, target_type, loc);
2186
return EmptyCast.Create (e, target_type);
2189
e = ExplicitUserConversion (ec, expr, target_type, loc);
2193
expr.Error_ValueCannotBeConverted (ec, target_type, true);