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.
14
using System.Collections.Generic;
17
using IKVM.Reflection.Emit;
19
using System.Reflection.Emit;
22
namespace Mono.CSharp {
25
// A container class for all the conversion operations
30
// From a one-dimensional array-type S[] to System.Collections.IList<T> and base
31
// interfaces of this interface, provided there is an implicit reference conversion
34
static bool ArrayToIList (ArrayContainer array, TypeSpec list, bool isExplicit)
36
if (array.Rank != 1 || !list.IsGenericIterateInterface)
39
var arg_type = list.TypeArguments[0];
40
if (array.Element == arg_type)
44
// Reject conversion from T[] to IList<U> even if T has U dependency
46
if (arg_type.IsGenericParameter)
50
return ExplicitReferenceConversionExists (array.Element, arg_type);
52
return ImplicitReferenceConversionExists (array.Element, arg_type);
55
static bool IList_To_Array(TypeSpec list, ArrayContainer array)
57
if (array.Rank != 1 || !list.IsGenericIterateInterface)
60
var arg_type = list.TypeArguments[0];
61
if (array.Element == arg_type)
64
return ImplicitReferenceConversionExists (array.Element, arg_type) || ExplicitReferenceConversionExists (array.Element, arg_type);
67
public static Expression ImplicitTypeParameterConversion (Expression expr, TypeParameterSpec expr_type, TypeSpec target_type)
70
// From T to a type parameter U, provided T depends on U
72
if (target_type.IsGenericParameter) {
73
if (expr_type.TypeArguments != null) {
74
foreach (var targ in expr_type.TypeArguments) {
75
if (!TypeSpecComparer.Override.IsEqual (target_type, targ))
79
return EmptyExpression.Null;
81
if (expr_type.IsReferenceType && !((TypeParameterSpec)target_type).IsReferenceType)
82
return new BoxedCast (expr, target_type);
84
return new ClassCast (expr, target_type);
92
// LAMESPEC: From T to dynamic type because it's like T to object
94
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
96
return EmptyExpression.Null;
98
if (expr_type.IsReferenceType)
99
return new ClassCast (expr, target_type);
101
return new BoxedCast (expr, target_type);
105
// From T to its effective base class C
106
// From T to any base class of C (it cannot contain dynamic or be of dynamic type)
107
// From T to any interface implemented by C
109
var base_type = expr_type.GetEffectiveBase ();
110
if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type, true)) {
112
return EmptyExpression.Null;
114
if (expr_type.IsReferenceType)
115
return new ClassCast (expr, target_type);
117
return new BoxedCast (expr, target_type);
120
if (target_type.IsInterface && expr_type.IsConvertibleToInterface (target_type)) {
122
return EmptyExpression.Null;
124
if (expr_type.IsReferenceType)
125
return new ClassCast (expr, target_type);
127
return new BoxedCast (expr, target_type);
133
static Expression ExplicitTypeParameterConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
135
var target_tp = target_type as TypeParameterSpec;
136
if (target_tp != null) {
137
if (target_tp.TypeArguments != null) {
138
foreach (var targ in target_tp.TypeArguments) {
139
if (!TypeSpecComparer.Override.IsEqual (source_type, targ))
142
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
146
if (target_tp.Interfaces != null) {
147
foreach (TypeSpec iface in target_tp.Interfaces) {
148
if (!TypeManager.IsGenericParameter (iface))
151
if (TypeManager.IsSubclassOf (source_type, iface))
152
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
159
if (target_type.IsInterface)
160
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
165
public static Expression ImplicitReferenceConversion (Expression expr, TypeSpec target_type, bool explicit_cast)
167
TypeSpec expr_type = expr.Type;
169
if (expr_type.Kind == MemberKind.TypeParameter)
170
return ImplicitTypeParameterConversion (expr, (TypeParameterSpec) expr.Type, target_type);
173
// from the null type to any reference-type.
175
NullLiteral nl = expr as NullLiteral;
177
return nl.ConvertImplicitly (target_type);
180
if (ImplicitReferenceConversionExists (expr_type, target_type)) {
182
// Avoid wrapping implicitly convertible reference type
187
return EmptyCast.Create (expr, target_type);
194
// Implicit reference conversions
196
public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type)
198
// It's here only to speed things up
199
if (target_type.IsStruct)
202
switch (expr_type.Kind) {
203
case MemberKind.TypeParameter:
204
return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null;
206
case MemberKind.Class:
208
// From any class-type to dynamic (+object to speed up common path)
210
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
213
if (target_type.IsClass) {
215
// Identity conversion, including dynamic erasure
217
if (TypeSpecComparer.IsEqual (expr_type, target_type))
221
// From any class-type S to any class-type T, provided S is derived from T
223
return TypeSpec.IsBaseClass (expr_type, target_type, true);
227
// From any class-type S to any interface-type T, provided S implements T
229
if (target_type.IsInterface)
230
return expr_type.ImplementsInterface (target_type, true);
234
case MemberKind.ArrayType:
236
// Identity array conversion
238
if (expr_type == target_type)
242
// From any array-type to System.Array
244
switch (target_type.BuiltinType) {
245
case BuiltinTypeSpec.Type.Array:
246
case BuiltinTypeSpec.Type.Object:
247
case BuiltinTypeSpec.Type.Dynamic:
251
var expr_type_array = (ArrayContainer) expr_type;
252
var target_type_array = target_type as ArrayContainer;
255
// From an array-type S to an array-type of type T
257
if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) {
260
// Both SE and TE are reference-types. TE check is defered
261
// to ImplicitReferenceConversionExists
263
TypeSpec expr_element_type = expr_type_array.Element;
264
if (!TypeSpec.IsReferenceType (expr_element_type))
268
// An implicit reference conversion exists from SE to TE
270
return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element);
274
// From any array-type to the interfaces it implements
276
if (target_type.IsInterface) {
277
if (expr_type.ImplementsInterface (target_type, false))
280
// from an array-type of type T to IList<T>
281
if (ArrayToIList (expr_type_array, target_type, false))
287
case MemberKind.Delegate:
289
// From any delegate-type to System.Delegate (and its base types)
291
switch (target_type.BuiltinType) {
292
case BuiltinTypeSpec.Type.Delegate:
293
case BuiltinTypeSpec.Type.MulticastDelegate:
294
case BuiltinTypeSpec.Type.Object:
295
case BuiltinTypeSpec.Type.Dynamic:
300
// Identity conversion, including dynamic erasure
302
if (TypeSpecComparer.IsEqual (expr_type, target_type))
306
// From any delegate-type to the interfaces it implements
307
// From any reference-type to an delegate type if is variance-convertible
309
return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type);
311
case MemberKind.Interface:
313
// Identity conversion, including dynamic erasure
315
if (TypeSpecComparer.IsEqual (expr_type, target_type))
319
// From any interface type S to interface-type T
320
// From any reference-type to an interface if is variance-convertible
322
if (target_type.IsInterface)
323
return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true);
325
return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
329
// from the null literal to any reference-type.
331
if (expr_type == InternalType.NullLiteral) {
332
// Exlude internal compiler types
333
if (target_type.Kind == MemberKind.InternalCompilerType)
334
return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
336
return TypeSpec.IsReferenceType (target_type);
342
public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
344
switch (target_type.BuiltinType) {
346
// From any non-nullable-value-type to the type object and dynamic
348
case BuiltinTypeSpec.Type.Object:
349
case BuiltinTypeSpec.Type.Dynamic:
351
// From any non-nullable-value-type to the type System.ValueType
353
case BuiltinTypeSpec.Type.ValueType:
355
// No ned to check for nullable type as underlying type is always convertible
357
if (!TypeSpec.IsValueType (expr_type))
360
return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
362
case BuiltinTypeSpec.Type.Enum:
364
// From any enum-type to the type System.Enum.
366
if (expr_type.IsEnum)
367
return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
373
// From a nullable-type to a reference type, if a boxing conversion exists from
374
// the underlying type to the reference type
376
if (expr_type.IsNullableType) {
377
if (!TypeSpec.IsReferenceType (target_type))
380
var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
382
// "cast" underlying type to target type to emit correct InvalidCastException when
383
// underlying hierarchy changes without recompilation
384
if (res != null && expr != null)
385
res = new UnboxCast (res, target_type);
391
// A value type has a boxing conversion to an interface type I if it has a boxing conversion
392
// to an interface or delegate type I0 and I0 is variance-convertible to I
394
if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) {
395
return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
401
public static Expression ImplicitNulableConversion (ResolveContext ec, Expression expr, TypeSpec target_type)
403
TypeSpec expr_type = expr.Type;
406
// From null to any nullable type
408
if (expr_type == InternalType.NullLiteral)
409
return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location);
412
TypeSpec t_el = Nullable.NullableInfo.GetUnderlyingType (target_type);
415
if (expr_type.IsNullableType)
416
expr_type = Nullable.NullableInfo.GetUnderlyingType (expr_type);
419
// Predefined implicit identity or implicit numeric conversion
420
// has to exist between underlying type S and underlying type T
423
// conversion exists only mode
425
if (TypeSpecComparer.IsEqual (expr_type, t_el))
426
return EmptyExpression.Null;
428
if (expr is Constant)
429
return ((Constant) expr).ConvertImplicitly (t_el);
431
return ImplicitNumericConversion (null, expr_type, t_el);
435
if (expr_type != expr.Type)
436
unwrap = Nullable.Unwrap.Create (expr);
440
Expression conv = unwrap;
441
if (!TypeSpecComparer.IsEqual (expr_type, t_el)) {
442
if (conv is Constant)
443
conv = ((Constant)conv).ConvertImplicitly (t_el);
445
conv = ImplicitNumericConversion (conv, expr_type, t_el);
451
if (expr_type != expr.Type)
452
return new Nullable.Lifted (conv, unwrap, target_type).Resolve (ec);
454
return Nullable.Wrap.Create (conv, target_type);
458
/// Implicit Numeric Conversions.
460
/// expr is the expression to convert, returns a new expression of type
461
/// target_type or null if an implicit conversion is not possible.
463
public static Expression ImplicitNumericConversion (Expression expr, TypeSpec target_type)
465
return ImplicitNumericConversion (expr, expr.Type, target_type);
468
static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
470
switch (expr_type.BuiltinType) {
471
case BuiltinTypeSpec.Type.SByte:
473
// From sbyte to short, int, long, float, double, decimal
475
switch (target_type.BuiltinType) {
476
case BuiltinTypeSpec.Type.Int:
477
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
478
case BuiltinTypeSpec.Type.Long:
479
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
480
case BuiltinTypeSpec.Type.Double:
481
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
482
case BuiltinTypeSpec.Type.Float:
483
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
484
case BuiltinTypeSpec.Type.Short:
485
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
486
case BuiltinTypeSpec.Type.Decimal:
487
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
492
case BuiltinTypeSpec.Type.Byte:
494
// From byte to short, ushort, int, uint, long, ulong, float, double, decimal
496
switch (target_type.BuiltinType) {
497
case BuiltinTypeSpec.Type.Int:
498
case BuiltinTypeSpec.Type.UInt:
499
case BuiltinTypeSpec.Type.Short:
500
case BuiltinTypeSpec.Type.UShort:
501
return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
502
case BuiltinTypeSpec.Type.ULong:
503
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
504
case BuiltinTypeSpec.Type.Long:
505
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
506
case BuiltinTypeSpec.Type.Float:
507
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
508
case BuiltinTypeSpec.Type.Double:
509
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
510
case BuiltinTypeSpec.Type.Decimal:
511
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
514
case BuiltinTypeSpec.Type.Short:
516
// From short to int, long, float, double, decimal
518
switch (target_type.BuiltinType) {
519
case BuiltinTypeSpec.Type.Int:
520
return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
521
case BuiltinTypeSpec.Type.Long:
522
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
523
case BuiltinTypeSpec.Type.Double:
524
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
525
case BuiltinTypeSpec.Type.Float:
526
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
527
case BuiltinTypeSpec.Type.Decimal:
528
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
531
case BuiltinTypeSpec.Type.UShort:
533
// From ushort to int, uint, long, ulong, float, double, decimal
535
switch (target_type.BuiltinType) {
536
case BuiltinTypeSpec.Type.Int:
537
case BuiltinTypeSpec.Type.UInt:
538
return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
539
case BuiltinTypeSpec.Type.ULong:
540
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
541
case BuiltinTypeSpec.Type.Long:
542
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
543
case BuiltinTypeSpec.Type.Double:
544
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
545
case BuiltinTypeSpec.Type.Float:
546
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
547
case BuiltinTypeSpec.Type.Decimal:
548
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
551
case BuiltinTypeSpec.Type.Int:
553
// From int to long, float, double, decimal
555
switch (target_type.BuiltinType) {
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.UInt:
568
// From uint to long, ulong, float, double, decimal
570
switch (target_type.BuiltinType) {
571
case BuiltinTypeSpec.Type.Long:
572
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
573
case BuiltinTypeSpec.Type.ULong:
574
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
575
case BuiltinTypeSpec.Type.Double:
576
return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
577
case BuiltinTypeSpec.Type.Float:
578
return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
579
case BuiltinTypeSpec.Type.Decimal:
580
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
583
case BuiltinTypeSpec.Type.Long:
585
// From long to float, double, decimal
587
switch (target_type.BuiltinType) {
588
case BuiltinTypeSpec.Type.Double:
589
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
590
case BuiltinTypeSpec.Type.Float:
591
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
592
case BuiltinTypeSpec.Type.Decimal:
593
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
596
case BuiltinTypeSpec.Type.ULong:
598
// From ulong to float, double, decimal
600
switch (target_type.BuiltinType) {
601
case BuiltinTypeSpec.Type.Double:
602
return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
603
case BuiltinTypeSpec.Type.Float:
604
return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
605
case BuiltinTypeSpec.Type.Decimal:
606
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
609
case BuiltinTypeSpec.Type.Char:
611
// From char to ushort, int, uint, long, ulong, float, double, decimal
613
switch (target_type.BuiltinType) {
614
case BuiltinTypeSpec.Type.UShort:
615
case BuiltinTypeSpec.Type.Int:
616
case BuiltinTypeSpec.Type.UInt:
617
return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
618
case BuiltinTypeSpec.Type.ULong:
619
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
620
case BuiltinTypeSpec.Type.Long:
621
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
622
case BuiltinTypeSpec.Type.Float:
623
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
624
case BuiltinTypeSpec.Type.Double:
625
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
626
case BuiltinTypeSpec.Type.Decimal:
627
return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
630
case BuiltinTypeSpec.Type.Float:
634
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
635
return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
643
// Full version of implicit conversion
645
public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type)
647
if (ImplicitStandardConversionExists (expr, target_type))
650
if (expr.Type == InternalType.AnonymousMethod) {
651
if (!target_type.IsDelegate && !target_type.IsExpressionTreeType)
654
AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
655
return ame.ImplicitStandardConversionExists (ec, target_type);
658
if (expr.eclass == ExprClass.MethodGroup) {
659
if (target_type.IsDelegate && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) {
660
MethodGroupExpr mg = expr as MethodGroupExpr;
662
return DelegateCreation.ImplicitStandardConversionExists (ec, mg, target_type);
668
// Conversion from __arglist to System.ArgIterator
669
if (expr.Type == InternalType.Arglist)
670
return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec;
672
return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null;
676
// Implicit standard conversion (only core conversions are used here)
678
public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type)
681
// Identity conversions
682
// Implicit numeric conversions
683
// Implicit nullable conversions
684
// Implicit reference conversions
685
// Boxing conversions
686
// Implicit constant expression conversions
687
// Implicit conversions involving type parameters
690
TypeSpec expr_type = expr.Type;
692
if (expr_type == target_type)
695
if (target_type.IsNullableType)
696
return ImplicitNulableConversion (null, expr, target_type) != null;
698
if (ImplicitNumericConversion (null, expr_type, target_type) != null)
701
if (ImplicitReferenceConversionExists (expr_type, target_type))
704
if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
708
// Implicit Constant Expression Conversions
710
if (expr is IntConstant){
711
int value = ((IntConstant) expr).Value;
712
switch (target_type.BuiltinType) {
713
case BuiltinTypeSpec.Type.SByte:
714
if (value >= SByte.MinValue && value <= SByte.MaxValue)
717
case BuiltinTypeSpec.Type.Byte:
718
if (value >= 0 && value <= Byte.MaxValue)
721
case BuiltinTypeSpec.Type.Short:
722
if (value >= Int16.MinValue && value <= Int16.MaxValue)
725
case BuiltinTypeSpec.Type.UShort:
726
if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
729
case BuiltinTypeSpec.Type.UInt:
733
case BuiltinTypeSpec.Type.ULong:
735
// we can optimize this case: a positive int32
736
// always fits on a uint64. But we need an opcode
746
if (expr is LongConstant && target_type.BuiltinType == BuiltinTypeSpec.Type.ULong){
748
// Try the implicit constant expression conversion
749
// from long to ulong, instead of a nice routine,
752
long v = ((LongConstant) expr).Value;
757
if (expr is IntegralConstant && target_type.IsEnum) {
758
var i = (IntegralConstant) expr;
760
// LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
762
// An implicit enumeration conversion permits the decimal-integer-literal 0
763
// to be converted to any enum-type and to any nullable-type whose underlying
764
// type is an enum-type
766
return i.IsZeroInteger;
769
// Implicit dynamic conversion
770
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
771
switch (target_type.Kind) {
772
case MemberKind.ArrayType:
773
case MemberKind.Class:
774
case MemberKind.Struct:
775
case MemberKind.Delegate:
776
case MemberKind.Enum:
777
case MemberKind.Interface:
778
case MemberKind.TypeParameter:
782
// dynamic to __arglist
783
if (target_type == InternalType.Arglist)
790
// In an unsafe context implicit conversions is extended to include
792
// From any pointer-type to the type void*
793
// From the null literal to any pointer-type.
795
// LAMESPEC: The specification claims this conversion is allowed in implicit conversion but
796
// in reality implicit standard conversion uses it
798
if (target_type.IsPointer && expr.Type.IsPointer && ((PointerContainer) target_type).Element.Kind == MemberKind.Void)
802
// Struct identity conversion, including dynamic erasure
804
if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
811
/// Finds "most encompassed type" according to the spec (13.4.2)
812
/// amongst the methods in the MethodGroupExpr
814
public static TypeSpec FindMostEncompassedType (IEnumerable<TypeSpec> types)
816
TypeSpec best = null;
817
EmptyExpression expr;
819
foreach (TypeSpec t in types) {
825
expr = new EmptyExpression (t);
826
if (ImplicitStandardConversionExists (expr, best))
830
expr = new EmptyExpression (best);
831
foreach (TypeSpec t in types) {
834
if (!ImplicitStandardConversionExists (expr, t)) {
844
// Finds the most encompassing type (type into which all other
845
// types can convert to) amongst the types in the given set
847
static TypeSpec FindMostEncompassingType (IList<TypeSpec> types)
849
if (types.Count == 0)
852
if (types.Count == 1)
855
TypeSpec best = null;
856
for (int i = 0; i < types.Count; ++i) {
858
for (; ii < types.Count; ++ii) {
862
var expr = new EmptyExpression (types[ii]);
863
if (!ImplicitStandardConversionExists (expr, types [i])) {
877
// Indicates multiple best types
878
return InternalType.FakeInternalType;
885
// Finds the most specific source Sx according to the rules of the spec (13.4.4)
886
// by making use of FindMostEncomp* methods. Applies the correct rules separately
887
// for explicit and implicit conversion operators.
889
static TypeSpec FindMostSpecificSource (List<MethodSpec> list, TypeSpec sourceType, Expression source, bool apply_explicit_conv_rules)
891
var src_types_set = new TypeSpec [list.Count];
894
// Try exact match first, if any operator converts from S then Sx = S
896
for (int i = 0; i < src_types_set.Length; ++i) {
897
TypeSpec param_type = list [i].Parameters.Types [0];
899
if (param_type == sourceType)
902
src_types_set [i] = param_type;
906
// Explicit Conv rules
908
if (apply_explicit_conv_rules) {
909
var candidate_set = new List<TypeSpec> ();
911
foreach (TypeSpec param_type in src_types_set){
912
if (ImplicitStandardConversionExists (source, param_type))
913
candidate_set.Add (param_type);
916
if (candidate_set.Count != 0)
917
return FindMostEncompassedType (candidate_set);
923
if (apply_explicit_conv_rules)
924
return FindMostEncompassingType (src_types_set);
926
return FindMostEncompassedType (src_types_set);
930
/// Finds the most specific target Tx according to section 13.4.4
932
static public TypeSpec FindMostSpecificTarget (IList<MethodSpec> list,
933
TypeSpec target, bool apply_explicit_conv_rules)
935
var tgt_types_set = new List<TypeSpec> ();
938
// If any operator converts to T then Tx = T
940
foreach (var mi in list){
941
TypeSpec ret_type = mi.ReturnType;
942
if (ret_type == target)
945
tgt_types_set.Add (ret_type);
949
// Explicit conv rules
951
if (apply_explicit_conv_rules) {
952
var candidate_set = new List<TypeSpec> ();
954
foreach (TypeSpec ret_type in tgt_types_set) {
955
var expr = new EmptyExpression (ret_type);
957
if (ImplicitStandardConversionExists (expr, target))
958
candidate_set.Add (ret_type);
961
if (candidate_set.Count != 0)
962
return FindMostEncompassingType (candidate_set);
966
// Okay, final case !
968
if (apply_explicit_conv_rules)
969
return FindMostEncompassedType (tgt_types_set);
971
return FindMostEncompassingType (tgt_types_set);
975
/// User-defined Implicit conversions
977
static public Expression ImplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
979
return UserDefinedConversion (ec, source, target, true, loc);
983
/// User-defined Explicit conversions
985
static Expression ExplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
987
return UserDefinedConversion (ec, source, target, false, loc);
990
static void FindApplicableUserDefinedConversionOperators (IList<MemberSpec> operators, Expression source, TypeSpec target, bool implicitOnly, ref List<MethodSpec> candidates)
992
if (source.Type.IsInterface) {
993
// Neither A nor B are interface-types
997
// For a conversion operator to be applicable, it must be possible
998
// to perform a standard conversion from the source type to
999
// the operand type of the operator, and it must be possible
1000
// to perform a standard conversion from the result type of
1001
// the operator to the target type.
1003
Expression texpr = null;
1005
foreach (MethodSpec op in operators) {
1007
// Can be null because MemberCache.GetUserOperator does not resize the array
1011
var t = op.Parameters.Types[0];
1012
if (source.Type != t && !ImplicitStandardConversionExists (source, t)) {
1016
if (!ImplicitStandardConversionExists (new EmptyExpression (t), source.Type))
1026
if (t.IsNullableType)
1027
t = Nullable.NullableInfo.GetUnderlyingType (t);
1029
if (!ImplicitStandardConversionExists (new EmptyExpression (t), target)) {
1034
texpr = new EmptyExpression (target);
1036
if (!ImplicitStandardConversionExists (texpr, t))
1041
if (candidates == null)
1042
candidates = new List<MethodSpec> ();
1044
candidates.Add (op);
1049
// User-defined conversions
1051
static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, Location loc)
1053
List<MethodSpec> candidates = null;
1056
// If S or T are nullable types, source_type and target_type are their underlying types
1057
// otherwise source_type and target_type are equal to S and T respectively.
1059
TypeSpec source_type = source.Type;
1060
TypeSpec target_type = target;
1061
Expression source_type_expr;
1063
if (source_type.IsNullableType) {
1064
// No implicit conversion S? -> T for non-reference types
1065
if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType)
1068
source_type_expr = Nullable.Unwrap.Create (source);
1069
source_type = source_type_expr.Type;
1071
source_type_expr = source;
1074
if (target_type.IsNullableType)
1075
target_type = Nullable.NullableInfo.GetUnderlyingType (target_type);
1077
// Only these containers can contain a user defined implicit or explicit operators
1078
const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter;
1080
if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1081
bool declared_only = source_type.IsStruct;
1083
var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only);
1084
if (operators != null) {
1085
FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1088
if (!implicitOnly) {
1089
operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only);
1090
if (operators != null) {
1091
FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1096
if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1097
bool declared_only = target.IsStruct || implicitOnly;
1099
var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only);
1100
if (operators != null) {
1101
FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1104
if (!implicitOnly) {
1105
operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only);
1106
if (operators != null) {
1107
FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1112
if (candidates == null)
1116
// Find the most specific conversion operator
1118
MethodSpec most_specific_operator;
1120
if (candidates.Count == 1) {
1121
most_specific_operator = candidates[0];
1122
s_x = most_specific_operator.Parameters.Types[0];
1123
t_x = most_specific_operator.ReturnType;
1126
// Pass original source type to find the best match against input type and
1127
// not the unwrapped expression
1129
s_x = FindMostSpecificSource (candidates, source.Type, source_type_expr, !implicitOnly);
1133
t_x = FindMostSpecificTarget (candidates, target, !implicitOnly);
1137
most_specific_operator = null;
1138
for (int i = 0; i < candidates.Count; ++i) {
1139
if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) {
1140
most_specific_operator = candidates[i];
1145
if (most_specific_operator == null) {
1146
MethodSpec ambig_arg = null;
1147
foreach (var candidate in candidates) {
1148
if (candidate.ReturnType == t_x)
1149
most_specific_operator = candidate;
1150
else if (candidate.Parameters.Types[0] == s_x)
1151
ambig_arg = candidate;
1154
ec.Report.Error (457, loc,
1155
"Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'",
1156
ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (),
1157
source.Type.GetSignatureForError (), target.GetSignatureForError ());
1159
return ErrorExpression.Instance;
1164
// Convert input type when it's different to best operator argument
1166
if (s_x != source_type) {
1167
var c = source as Constant;
1169
source = c.TryReduce (ec, s_x, loc);
1171
source = implicitOnly ?
1172
ImplicitConversionStandard (ec, source_type_expr, s_x, loc) :
1173
ExplicitConversionStandard (ec, source_type_expr, s_x, loc);
1176
source = source_type_expr;
1179
source = new UserCast (most_specific_operator, source, loc).Resolve (ec);
1182
// Convert result type when it's different to best operator return type
1184
if (t_x != target_type) {
1186
// User operator is of T?, no need to lift it
1188
if (t_x == target && t_x.IsNullableType)
1191
source = implicitOnly ?
1192
ImplicitConversionStandard (ec, source, target_type, loc) :
1193
ExplicitConversionStandard (ec, source, target_type, loc);
1200
// Source expression is of nullable type, lift the result in the case it's null and
1201
// not nullable/lifted user operator is used
1203
if (source_type_expr is Nullable.Unwrap && !s_x.IsNullableType && (TypeSpec.IsReferenceType (target) || target_type != target))
1204
source = new Nullable.Lifted (source, source_type_expr, target).Resolve (ec);
1205
else if (target_type != target)
1206
source = Nullable.Wrap.Create (source, target);
1212
/// Converts implicitly the resolved expression `expr' into the
1213
/// `target_type'. It returns a new expression that can be used
1214
/// in a context that expects a `target_type'.
1216
static public Expression ImplicitConversion (ResolveContext ec, Expression expr,
1217
TypeSpec target_type, Location loc)
1221
if (target_type == null)
1222
throw new Exception ("Target type is null");
1224
e = ImplicitConversionStandard (ec, expr, target_type, loc);
1228
e = ImplicitUserConversion (ec, expr, target_type, loc);
1237
/// Attempts to apply the `Standard Implicit
1238
/// Conversion' rules to the expression `expr' into
1239
/// the `target_type'. It returns a new expression
1240
/// that can be used in a context that expects a
1243
/// This is different from `ImplicitConversion' in that the
1244
/// user defined implicit conversions are excluded.
1246
static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr,
1247
TypeSpec target_type, Location loc)
1249
return ImplicitConversionStandard (ec, expr, target_type, loc, false);
1252
static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast)
1254
if (expr.eclass == ExprClass.MethodGroup){
1255
if (!TypeManager.IsDelegateType (target_type)){
1260
// Only allow anonymous method conversions on post ISO_1
1262
if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){
1263
MethodGroupExpr mg = expr as MethodGroupExpr;
1265
return ImplicitDelegateCreation.Create (
1266
ec, mg, target_type, loc);
1270
TypeSpec expr_type = expr.Type;
1273
if (expr_type == target_type) {
1274
if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod)
1279
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1280
switch (target_type.Kind) {
1281
case MemberKind.ArrayType:
1282
case MemberKind.Class:
1283
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object)
1284
return EmptyCast.Create (expr, target_type);
1286
goto case MemberKind.Struct;
1287
case MemberKind.Struct:
1288
case MemberKind.Delegate:
1289
case MemberKind.Enum:
1290
case MemberKind.Interface:
1291
case MemberKind.TypeParameter:
1292
Arguments args = new Arguments (1);
1293
args.Add (new Argument (expr));
1294
return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec);
1300
if (target_type.IsNullableType)
1301
return ImplicitNulableConversion (ec, expr, target_type);
1304
// Attempt to do the implicit constant expression conversions
1306
Constant c = expr as Constant;
1309
c = c.ConvertImplicitly (target_type);
1311
Console.WriteLine ("Conversion error happened in line {0}", loc);
1318
e = ImplicitNumericConversion (expr, expr_type, target_type);
1322
e = ImplicitReferenceConversion (expr, target_type, explicit_cast);
1326
e = ImplicitBoxingConversion (expr, expr_type, target_type);
1330
if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)){
1331
var i = (IntegralConstant) expr;
1333
// LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
1335
// An implicit enumeration conversion permits the decimal-integer-literal 0
1336
// to be converted to any enum-type and to any nullable-type whose underlying
1337
// type is an enum-type
1339
if (i.IsZeroInteger) {
1340
// Recreate 0 literal to remove any collected conversions
1341
return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type);
1346
var target_pc = target_type as PointerContainer;
1347
if (target_pc != null) {
1348
if (expr_type.IsPointer) {
1350
// Pointer types are same when they have same element types
1352
if (expr_type == target_pc)
1355
if (target_pc.Element.Kind == MemberKind.Void)
1356
return EmptyCast.Create (expr, target_type);
1361
if (expr_type == InternalType.NullLiteral)
1362
return new NullPointer (target_type, loc);
1366
if (expr_type == InternalType.AnonymousMethod){
1367
AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
1368
Expression am = ame.Compatible (ec, target_type);
1370
return am.Resolve (ec);
1373
if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec)
1377
// dynamic erasure conversion on value types
1379
if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
1380
return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type);
1386
/// Attempts to implicitly convert `source' into `target_type', using
1387
/// ImplicitConversion. If there is no implicit conversion, then
1388
/// an error is signaled
1390
static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
1391
TypeSpec target_type, Location loc)
1393
Expression e = ImplicitConversion (ec, source, target_type, loc);
1397
source.Error_ValueCannotBeConverted (ec, loc, target_type, false);
1402
/// Performs the explicit numeric conversions
1404
/// There are a few conversions that are not part of the C# standard,
1405
/// they were interim hacks in the C# compiler that were supposed to
1406
/// become explicit operators in the UIntPtr class and IntPtr class,
1407
/// but for historical reasons it did not happen, so the C# compiler
1408
/// ended up with these special hacks.
1410
/// See bug 59800 for details.
1412
/// The conversion are:
1422
public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type)
1424
// Not all predefined explicit numeric conversion are
1425
// defined here, for some of them (mostly IntPtr/UIntPtr) we
1426
// defer to user-operator handling which is now perfect but
1429
// LAMESPEC: Undocumented IntPtr/UIntPtr conversions
1430
// IntPtr -> uint uses int
1431
// UIntPtr -> long uses ulong
1434
switch (expr.Type.BuiltinType) {
1435
case BuiltinTypeSpec.Type.SByte:
1437
// From sbyte to byte, ushort, uint, ulong, char, uintptr
1439
switch (target_type.BuiltinType) {
1440
case BuiltinTypeSpec.Type.Byte:
1441
return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
1442
case BuiltinTypeSpec.Type.UShort:
1443
return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
1444
case BuiltinTypeSpec.Type.UInt:
1445
return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
1446
case BuiltinTypeSpec.Type.ULong:
1447
return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
1448
case BuiltinTypeSpec.Type.Char:
1449
return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
1451
// One of the built-in conversions that belonged in the class library
1452
case BuiltinTypeSpec.Type.UIntPtr:
1453
return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true);
1456
case BuiltinTypeSpec.Type.Byte:
1458
// From byte to sbyte and char
1460
switch (target_type.BuiltinType) {
1461
case BuiltinTypeSpec.Type.SByte:
1462
return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
1463
case BuiltinTypeSpec.Type.Char:
1464
return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
1467
case BuiltinTypeSpec.Type.Short:
1469
// From short to sbyte, byte, ushort, uint, ulong, char, uintptr
1471
switch (target_type.BuiltinType) {
1472
case BuiltinTypeSpec.Type.SByte:
1473
return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
1474
case BuiltinTypeSpec.Type.Byte:
1475
return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
1476
case BuiltinTypeSpec.Type.UShort:
1477
return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
1478
case BuiltinTypeSpec.Type.UInt:
1479
return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
1480
case BuiltinTypeSpec.Type.ULong:
1481
return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
1482
case BuiltinTypeSpec.Type.Char:
1483
return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
1485
// One of the built-in conversions that belonged in the class library
1486
case BuiltinTypeSpec.Type.UIntPtr:
1487
return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1490
case BuiltinTypeSpec.Type.UShort:
1492
// From ushort to sbyte, byte, short, char
1494
switch (target_type.BuiltinType) {
1495
case BuiltinTypeSpec.Type.SByte:
1496
return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
1497
case BuiltinTypeSpec.Type.Byte:
1498
return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
1499
case BuiltinTypeSpec.Type.Short:
1500
return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
1501
case BuiltinTypeSpec.Type.Char:
1502
return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
1505
case BuiltinTypeSpec.Type.Int:
1507
// From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
1509
switch (target_type.BuiltinType) {
1510
case BuiltinTypeSpec.Type.SByte:
1511
return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
1512
case BuiltinTypeSpec.Type.Byte:
1513
return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
1514
case BuiltinTypeSpec.Type.Short:
1515
return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
1516
case BuiltinTypeSpec.Type.UShort:
1517
return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
1518
case BuiltinTypeSpec.Type.UInt:
1519
return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
1520
case BuiltinTypeSpec.Type.ULong:
1521
return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
1522
case BuiltinTypeSpec.Type.Char:
1523
return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
1525
// One of the built-in conversions that belonged in the class library
1526
case BuiltinTypeSpec.Type.UIntPtr:
1527
return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1530
case BuiltinTypeSpec.Type.UInt:
1532
// From uint to sbyte, byte, short, ushort, int, char
1534
switch (target_type.BuiltinType) {
1535
case BuiltinTypeSpec.Type.SByte:
1536
return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
1537
case BuiltinTypeSpec.Type.Byte:
1538
return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
1539
case BuiltinTypeSpec.Type.Short:
1540
return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
1541
case BuiltinTypeSpec.Type.UShort:
1542
return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
1543
case BuiltinTypeSpec.Type.Int:
1544
return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
1545
case BuiltinTypeSpec.Type.Char:
1546
return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
1549
case BuiltinTypeSpec.Type.Long:
1551
// From long to sbyte, byte, short, ushort, int, uint, ulong, char
1553
switch (target_type.BuiltinType) {
1554
case BuiltinTypeSpec.Type.SByte:
1555
return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
1556
case BuiltinTypeSpec.Type.Byte:
1557
return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
1558
case BuiltinTypeSpec.Type.Short:
1559
return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
1560
case BuiltinTypeSpec.Type.UShort:
1561
return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
1562
case BuiltinTypeSpec.Type.Int:
1563
return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
1564
case BuiltinTypeSpec.Type.UInt:
1565
return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
1566
case BuiltinTypeSpec.Type.ULong:
1567
return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
1568
case BuiltinTypeSpec.Type.Char:
1569
return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
1572
case BuiltinTypeSpec.Type.ULong:
1574
// From ulong to sbyte, byte, short, ushort, int, uint, long, char
1576
switch (target_type.BuiltinType) {
1577
case BuiltinTypeSpec.Type.SByte:
1578
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
1579
case BuiltinTypeSpec.Type.Byte:
1580
return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
1581
case BuiltinTypeSpec.Type.Short:
1582
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
1583
case BuiltinTypeSpec.Type.UShort:
1584
return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
1585
case BuiltinTypeSpec.Type.Int:
1586
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
1587
case BuiltinTypeSpec.Type.UInt:
1588
return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
1589
case BuiltinTypeSpec.Type.Long:
1590
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
1591
case BuiltinTypeSpec.Type.Char:
1592
return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
1594
// One of the built-in conversions that belonged in the class library
1595
case BuiltinTypeSpec.Type.IntPtr:
1596
return new OperatorCast (EmptyCast.Create (expr, rc.BuiltinTypes.Long), target_type, true);
1599
case BuiltinTypeSpec.Type.Char:
1601
// From char to sbyte, byte, short
1603
switch (target_type.BuiltinType) {
1604
case BuiltinTypeSpec.Type.SByte:
1605
return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
1606
case BuiltinTypeSpec.Type.Byte:
1607
return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
1608
case BuiltinTypeSpec.Type.Short:
1609
return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
1612
case BuiltinTypeSpec.Type.Float:
1614
// From float to sbyte, byte, short,
1615
// ushort, int, uint, long, ulong, char
1618
switch (target_type.BuiltinType) {
1619
case BuiltinTypeSpec.Type.SByte:
1620
return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
1621
case BuiltinTypeSpec.Type.Byte:
1622
return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
1623
case BuiltinTypeSpec.Type.Short:
1624
return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
1625
case BuiltinTypeSpec.Type.UShort:
1626
return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
1627
case BuiltinTypeSpec.Type.Int:
1628
return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
1629
case BuiltinTypeSpec.Type.UInt:
1630
return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
1631
case BuiltinTypeSpec.Type.Long:
1632
return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
1633
case BuiltinTypeSpec.Type.ULong:
1634
return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
1635
case BuiltinTypeSpec.Type.Char:
1636
return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
1637
case BuiltinTypeSpec.Type.Decimal:
1638
return new OperatorCast (expr, target_type, true);
1641
case BuiltinTypeSpec.Type.Double:
1643
// From double to sbyte, byte, short,
1644
// ushort, int, uint, long, ulong,
1645
// char, float or decimal
1647
switch (target_type.BuiltinType) {
1648
case BuiltinTypeSpec.Type.SByte:
1649
return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
1650
case BuiltinTypeSpec.Type.Byte:
1651
return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
1652
case BuiltinTypeSpec.Type.Short:
1653
return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
1654
case BuiltinTypeSpec.Type.UShort:
1655
return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
1656
case BuiltinTypeSpec.Type.Int:
1657
return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
1658
case BuiltinTypeSpec.Type.UInt:
1659
return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
1660
case BuiltinTypeSpec.Type.Long:
1661
return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
1662
case BuiltinTypeSpec.Type.ULong:
1663
return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
1664
case BuiltinTypeSpec.Type.Char:
1665
return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
1666
case BuiltinTypeSpec.Type.Float:
1667
return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
1668
case BuiltinTypeSpec.Type.Decimal:
1669
return new OperatorCast (expr, target_type, true);
1672
case BuiltinTypeSpec.Type.UIntPtr:
1674
// Various built-in conversions that belonged in the class library
1676
// from uintptr to sbyte, short, int32
1678
switch (target_type.BuiltinType) {
1679
case BuiltinTypeSpec.Type.SByte:
1680
return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I1);
1681
case BuiltinTypeSpec.Type.Short:
1682
return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I2);
1683
case BuiltinTypeSpec.Type.Int:
1684
return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type);
1685
case BuiltinTypeSpec.Type.UInt:
1686
return new OperatorCast (expr, expr.Type, target_type, true);
1687
case BuiltinTypeSpec.Type.Long:
1688
return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.ULong, true), target_type);
1691
case BuiltinTypeSpec.Type.IntPtr:
1692
if (target_type.BuiltinType == BuiltinTypeSpec.Type.UInt)
1693
return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Int, true), target_type);
1694
if (target_type.BuiltinType == BuiltinTypeSpec.Type.ULong)
1695
return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Long, true), target_type);
1698
case BuiltinTypeSpec.Type.Decimal:
1699
// From decimal to sbyte, byte, short,
1700
// ushort, int, uint, long, ulong, char,
1702
switch (target_type.BuiltinType) {
1703
case BuiltinTypeSpec.Type.SByte:
1704
case BuiltinTypeSpec.Type.Byte:
1705
case BuiltinTypeSpec.Type.Short:
1706
case BuiltinTypeSpec.Type.UShort:
1707
case BuiltinTypeSpec.Type.Int:
1708
case BuiltinTypeSpec.Type.UInt:
1709
case BuiltinTypeSpec.Type.Long:
1710
case BuiltinTypeSpec.Type.ULong:
1711
case BuiltinTypeSpec.Type.Char:
1712
case BuiltinTypeSpec.Type.Float:
1713
case BuiltinTypeSpec.Type.Double:
1714
return new OperatorCast (expr, expr.Type, target_type, true);
1724
/// Returns whether an explicit reference conversion can be performed
1725
/// from source_type to target_type
1727
public static bool ExplicitReferenceConversionExists (TypeSpec source_type, TypeSpec target_type)
1729
Expression e = ExplicitReferenceConversion (null, source_type, target_type);
1733
if (e == EmptyExpression.Null)
1736
throw new InternalErrorException ("Invalid probing conversion result");
1740
/// Implements Explicit Reference conversions
1742
static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
1745
// From object to a generic parameter
1747
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type))
1748
return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1751
// Explicit type parameter conversion.
1753
if (source_type.Kind == MemberKind.TypeParameter)
1754
return ExplicitTypeParameterConversion (source, source_type, target_type);
1756
bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum;
1759
// Unboxing conversion from System.ValueType to any non-nullable-value-type
1761
if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type)
1762
return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1765
// From object or dynamic to any reference type or value type (unboxing)
1767
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1768
if (target_type.IsPointer)
1772
source == null ? EmptyExpression.Null :
1773
target_is_value_type ? new UnboxCast (source, target_type) :
1774
source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) :
1775
new ClassCast (source, target_type);
1779
// From any class S to any class-type T, provided S is a base class of T
1781
if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true))
1782
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1785
// From any interface-type S to to any class type T, provided T is not
1786
// sealed, or provided T implements S.
1788
if (source_type.Kind == MemberKind.Interface) {
1789
if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) {
1791
return EmptyExpression.Null;
1794
// Unboxing conversion from any interface-type to any non-nullable-value-type that
1795
// implements the interface-type
1797
return target_is_value_type ? new UnboxCast (source, target_type) : (Expression) new ClassCast (source, target_type);
1801
// From System.Collections.Generic.IList<T> and its base interfaces to a one-dimensional
1802
// array type S[], provided there is an implicit or explicit reference conversion from S to T.
1804
var target_array = target_type as ArrayContainer;
1805
if (target_array != null && IList_To_Array (source_type, target_array))
1806
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1811
var source_array = source_type as ArrayContainer;
1812
if (source_array != null) {
1813
var target_array = target_type as ArrayContainer;
1814
if (target_array != null) {
1816
// From System.Array to any array-type
1818
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array)
1819
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1822
// From an array type S with an element type Se to an array type T with an
1823
// element type Te provided all the following are true:
1824
// * S and T differe only in element type, in other words, S and T
1825
// have the same number of dimensions.
1826
// * Both Se and Te are reference types
1827
// * An explicit reference conversions exist from Se to Te
1829
if (source_array.Rank == target_array.Rank) {
1831
source_type = source_array.Element;
1832
if (!TypeSpec.IsReferenceType (source_type))
1835
var target_element = target_array.Element;
1836
if (!TypeSpec.IsReferenceType (target_element))
1839
if (ExplicitReferenceConversionExists (source_type, target_element))
1840
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1847
// From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces,
1848
// provided that there is an explicit reference conversion from S to T
1850
if (ArrayToIList (source_array, target_type, true))
1851
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1857
// From any class type S to any interface T, provides S is not sealed
1858
// and provided S does not implement T.
1860
if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type, true)) {
1861
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1865
// From System delegate to any delegate-type
1867
if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && TypeManager.IsDelegateType (target_type))
1868
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1871
// From variant generic delegate to same variant generic delegate type
1873
if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) {
1874
var tparams = source_type.MemberDefinition.TypeParameters;
1875
var targs_src = source_type.TypeArguments;
1876
var targs_dst = target_type.TypeArguments;
1878
for (i = 0; i < tparams.Length; ++i) {
1880
// If TP is invariant, types have to be identical
1882
if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i]))
1885
if (tparams[i].Variance == Variance.Covariant) {
1887
//If TP is covariant, an implicit or explicit identity or reference conversion is required
1889
if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1892
if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1895
} else if (tparams[i].Variance == Variance.Contravariant) {
1897
//If TP is contravariant, both are either identical or reference types
1899
if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i]))
1906
if (i == tparams.Length)
1907
return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1914
/// Performs an explicit conversion of the expression `expr' whose
1915
/// type is expr.Type to `target_type'.
1917
static public Expression ExplicitConversionCore (ResolveContext ec, Expression expr,
1918
TypeSpec target_type, Location loc)
1920
TypeSpec expr_type = expr.Type;
1922
// Explicit conversion includes implicit conversion and it used for enum underlying types too
1923
Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true);
1927
if (TypeManager.IsEnumType (expr_type)) {
1928
TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1929
Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type));
1930
if (underlying.Type == real_target)
1934
ne = ImplicitNumericConversion (underlying, real_target);
1937
ne = ExplicitNumericConversion (ec, underlying, real_target);
1940
// LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
1942
if (ne == null && (real_target.BuiltinType == BuiltinTypeSpec.Type.IntPtr || real_target.BuiltinType == BuiltinTypeSpec.Type.UIntPtr))
1943
ne = ExplicitUserConversion (ec, underlying, real_target, loc);
1945
return ne != null ? EmptyCast.Create (ne, target_type) : null;
1948
if (TypeManager.IsEnumType (target_type)) {
1950
// System.Enum can be unboxed to any enum-type
1952
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Enum)
1953
return new UnboxCast (expr, target_type);
1955
TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1957
if (expr_type == real_target)
1958
return EmptyCast.Create (expr, target_type);
1960
ne = ImplicitNumericConversion (expr, real_target);
1962
return EmptyCast.Create (ne, target_type);
1964
ne = ExplicitNumericConversion (ec, expr, real_target);
1966
return EmptyCast.Create (ne, target_type);
1969
// LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
1971
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.IntPtr || expr_type.BuiltinType == BuiltinTypeSpec.Type.UIntPtr) {
1972
ne = ExplicitUserConversion (ec, expr, real_target, loc);
1974
return ExplicitConversionCore (ec, ne, target_type, loc);
1977
ne = ExplicitNumericConversion (ec, expr, target_type);
1983
// Skip the ExplicitReferenceConversion because we can not convert
1984
// from Null to a ValueType, and ExplicitReference wont check against
1985
// null literal explicitly
1987
if (expr_type != InternalType.NullLiteral) {
1988
ne = ExplicitReferenceConversion (expr, expr_type, target_type);
1994
ne = ExplicitUnsafe (expr, target_type);
2002
public static Expression ExplicitUnsafe (Expression expr, TypeSpec target_type)
2004
TypeSpec expr_type = expr.Type;
2006
if (target_type.IsPointer){
2007
if (expr_type.IsPointer)
2008
return EmptyCast.Create (expr, target_type);
2010
switch (expr_type.BuiltinType) {
2011
case BuiltinTypeSpec.Type.SByte:
2012
case BuiltinTypeSpec.Type.Short:
2013
case BuiltinTypeSpec.Type.Int:
2014
return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
2016
case BuiltinTypeSpec.Type.UShort:
2017
case BuiltinTypeSpec.Type.UInt:
2018
case BuiltinTypeSpec.Type.Byte:
2019
return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2021
case BuiltinTypeSpec.Type.Long:
2022
return new ConvCast (expr, target_type, ConvCast.Mode.I8_I);
2024
case BuiltinTypeSpec.Type.ULong:
2025
return new ConvCast (expr, target_type, ConvCast.Mode.U8_I);
2029
if (expr_type.IsPointer){
2030
switch (target_type.BuiltinType) {
2031
case BuiltinTypeSpec.Type.SByte:
2032
return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
2033
case BuiltinTypeSpec.Type.Byte:
2034
return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
2035
case BuiltinTypeSpec.Type.Short:
2036
return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
2037
case BuiltinTypeSpec.Type.UShort:
2038
return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
2039
case BuiltinTypeSpec.Type.Int:
2040
return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
2041
case BuiltinTypeSpec.Type.UInt:
2042
return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
2043
case BuiltinTypeSpec.Type.Long:
2044
return new ConvCast (expr, target_type, ConvCast.Mode.I_I8);
2045
case BuiltinTypeSpec.Type.ULong:
2046
return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
2053
/// Same as ExplicitConversion, only it doesn't include user defined conversions
2055
static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr,
2056
TypeSpec target_type, Location l)
2058
int errors = ec.Report.Errors;
2059
Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
2060
if (ec.Report.Errors > errors)
2066
ne = ExplicitNumericConversion (ec, expr, target_type);
2070
ne = ExplicitReferenceConversion (expr, expr.Type, target_type);
2074
if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void)
2075
return EmptyCast.Create (expr, target_type);
2077
expr.Error_ValueCannotBeConverted (ec, l, target_type, true);
2082
/// Performs an explicit conversion of the expression `expr' whose
2083
/// type is expr.Type to `target_type'.
2085
static public Expression ExplicitConversion (ResolveContext ec, Expression expr,
2086
TypeSpec target_type, Location loc)
2088
Expression e = ExplicitConversionCore (ec, expr, target_type, loc);
2091
// Don't eliminate explicit precission casts
2094
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float)
2095
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
2097
if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
2098
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
2104
TypeSpec expr_type = expr.Type;
2105
if (target_type.IsNullableType) {
2108
if (expr_type.IsNullableType) {
2109
target = Nullable.NullableInfo.GetUnderlyingType (target_type);
2110
Expression unwrap = Nullable.Unwrap.Create (expr);
2111
e = ExplicitConversion (ec, unwrap, target, expr.Location);
2115
return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec);
2117
if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2118
return new UnboxCast (expr, target_type);
2121
target = TypeManager.GetTypeArguments (target_type) [0];
2122
e = ExplicitConversionCore (ec, expr, target, loc);
2124
return Nullable.Wrap.Create (e, target_type);
2125
} else if (expr_type.IsNullableType) {
2126
e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
2130
e = Nullable.Unwrap.Create (expr, false);
2131
e = ExplicitConversionCore (ec, e, target_type, loc);
2133
return EmptyCast.Create (e, target_type);
2136
e = ExplicitUserConversion (ec, expr, target_type, loc);
2140
expr.Error_ValueCannotBeConverted (ec, loc, target_type, true);