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 return ImplicitReferenceConversionExists (expr_type, target_type, true);
201 static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter)
203 // It's here only to speed things up
204 if (target_type.IsStruct)
207 switch (expr_type.Kind) {
208 case MemberKind.TypeParameter:
209 return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null &&
210 (!refOnlyTypeParameter || TypeSpec.IsReferenceType (expr_type));
212 case MemberKind.Class:
214 // From any class-type to dynamic (+object to speed up common path)
216 if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
219 if (target_type.IsClass) {
221 // Identity conversion, including dynamic erasure
223 if (TypeSpecComparer.IsEqual (expr_type, target_type))
227 // From any class-type S to any class-type T, provided S is derived from T
229 return TypeSpec.IsBaseClass (expr_type, target_type, true);
233 // From any class-type S to any interface-type T, provided S implements T
235 if (target_type.IsInterface)
236 return expr_type.ImplementsInterface (target_type, true);
240 case MemberKind.ArrayType:
242 // Identity array conversion
244 if (expr_type == target_type)
248 // From any array-type to System.Array
250 switch (target_type.BuiltinType) {
251 case BuiltinTypeSpec.Type.Array:
252 case BuiltinTypeSpec.Type.Object:
253 case BuiltinTypeSpec.Type.Dynamic:
257 var expr_type_array = (ArrayContainer) expr_type;
258 var target_type_array = target_type as ArrayContainer;
261 // From an array-type S to an array-type of type T
263 if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) {
266 // Both SE and TE are reference-types. TE check is defered
267 // to ImplicitReferenceConversionExists
269 TypeSpec expr_element_type = expr_type_array.Element;
270 if (!TypeSpec.IsReferenceType (expr_element_type))
274 // An implicit reference conversion exists from SE to TE
276 return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element);
280 // From any array-type to the interfaces it implements
282 if (target_type.IsInterface) {
283 if (expr_type.ImplementsInterface (target_type, false))
286 // from an array-type of type T to IList<T>
287 if (ArrayToIList (expr_type_array, target_type, false))
293 case MemberKind.Delegate:
295 // From any delegate-type to System.Delegate (and its base types)
297 switch (target_type.BuiltinType) {
298 case BuiltinTypeSpec.Type.Delegate:
299 case BuiltinTypeSpec.Type.MulticastDelegate:
300 case BuiltinTypeSpec.Type.Object:
301 case BuiltinTypeSpec.Type.Dynamic:
306 // Identity conversion, including dynamic erasure
308 if (TypeSpecComparer.IsEqual (expr_type, target_type))
312 // From any delegate-type to the interfaces it implements
313 // From any reference-type to an delegate type if is variance-convertible
315 return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type);
317 case MemberKind.Interface:
319 // Identity conversion, including dynamic erasure
321 if (TypeSpecComparer.IsEqual (expr_type, target_type))
325 // From any interface type S to interface-type T
326 // From any reference-type to an interface if is variance-convertible
328 if (target_type.IsInterface)
329 return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true);
331 return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
335 // from the null literal to any reference-type.
337 if (expr_type == InternalType.NullLiteral) {
338 // Exlude internal compiler types
339 if (target_type.Kind == MemberKind.InternalCompilerType)
340 return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
342 return TypeSpec.IsReferenceType (target_type);
348 public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
350 switch (target_type.BuiltinType) {
352 // From any non-nullable-value-type to the type object and dynamic
354 case BuiltinTypeSpec.Type.Object:
355 case BuiltinTypeSpec.Type.Dynamic:
357 // From any non-nullable-value-type to the type System.ValueType
359 case BuiltinTypeSpec.Type.ValueType:
361 // No ned to check for nullable type as underlying type is always convertible
363 if (!TypeSpec.IsValueType (expr_type))
366 return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
368 case BuiltinTypeSpec.Type.Enum:
370 // From any enum-type to the type System.Enum.
372 if (expr_type.IsEnum)
373 return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
379 // From a nullable-type to a reference type, if a boxing conversion exists from
380 // the underlying type to the reference type
382 if (expr_type.IsNullableType) {
383 if (!TypeSpec.IsReferenceType (target_type))
386 var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
388 // "cast" underlying type to target type to emit correct InvalidCastException when
389 // underlying hierarchy changes without recompilation
390 if (res != null && expr != null)
391 res = new UnboxCast (res, target_type);
397 // A value type has a boxing conversion to an interface type I if it has a boxing conversion
398 // to an interface or delegate type I0 and I0 is variance-convertible to I
400 if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) {
401 return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
407 public static Expression ImplicitNulableConversion (ResolveContext ec, Expression expr, TypeSpec target_type)
409 TypeSpec expr_type = expr.Type;
412 // From null to any nullable type
414 if (expr_type == InternalType.NullLiteral)
415 return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location);
418 TypeSpec t_el = Nullable.NullableInfo.GetUnderlyingType (target_type);
421 if (expr_type.IsNullableType)
422 expr_type = Nullable.NullableInfo.GetUnderlyingType (expr_type);
425 // Predefined implicit identity or implicit numeric conversion
426 // has to exist between underlying type S and underlying type T
429 // conversion exists only mode
431 if (TypeSpecComparer.IsEqual (expr_type, t_el))
432 return EmptyExpression.Null;
434 if (expr is Constant)
435 return ((Constant) expr).ConvertImplicitly (t_el);
437 return ImplicitNumericConversion (null, expr_type, t_el);
441 if (expr_type != expr.Type)
442 unwrap = Nullable.Unwrap.Create (expr);
446 Expression conv = unwrap;
447 if (!TypeSpecComparer.IsEqual (expr_type, t_el)) {
448 if (conv is Constant)
449 conv = ((Constant)conv).ConvertImplicitly (t_el);
451 conv = ImplicitNumericConversion (conv, expr_type, t_el);
457 if (expr_type != expr.Type)
458 return new Nullable.Lifted (conv, unwrap, target_type).Resolve (ec);
460 return Nullable.Wrap.Create (conv, target_type);
464 /// Implicit Numeric Conversions.
466 /// expr is the expression to convert, returns a new expression of type
467 /// target_type or null if an implicit conversion is not possible.
469 public static Expression ImplicitNumericConversion (Expression expr, TypeSpec target_type)
471 return ImplicitNumericConversion (expr, expr.Type, target_type);
474 static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
476 switch (expr_type.BuiltinType) {
477 case BuiltinTypeSpec.Type.SByte:
479 // From sbyte to short, int, long, float, double, decimal
481 switch (target_type.BuiltinType) {
482 case BuiltinTypeSpec.Type.Int:
483 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
484 case BuiltinTypeSpec.Type.Long:
485 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
486 case BuiltinTypeSpec.Type.Double:
487 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
488 case BuiltinTypeSpec.Type.Float:
489 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
490 case BuiltinTypeSpec.Type.Short:
491 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
492 case BuiltinTypeSpec.Type.Decimal:
493 return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
498 case BuiltinTypeSpec.Type.Byte:
500 // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
502 switch (target_type.BuiltinType) {
503 case BuiltinTypeSpec.Type.Int:
504 case BuiltinTypeSpec.Type.UInt:
505 case BuiltinTypeSpec.Type.Short:
506 case BuiltinTypeSpec.Type.UShort:
507 return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
508 case BuiltinTypeSpec.Type.ULong:
509 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
510 case BuiltinTypeSpec.Type.Long:
511 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
512 case BuiltinTypeSpec.Type.Float:
513 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
514 case BuiltinTypeSpec.Type.Double:
515 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
516 case BuiltinTypeSpec.Type.Decimal:
517 return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
520 case BuiltinTypeSpec.Type.Short:
522 // From short to int, long, float, double, decimal
524 switch (target_type.BuiltinType) {
525 case BuiltinTypeSpec.Type.Int:
526 return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
527 case BuiltinTypeSpec.Type.Long:
528 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
529 case BuiltinTypeSpec.Type.Double:
530 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
531 case BuiltinTypeSpec.Type.Float:
532 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
533 case BuiltinTypeSpec.Type.Decimal:
534 return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
537 case BuiltinTypeSpec.Type.UShort:
539 // From ushort to int, uint, long, ulong, float, double, decimal
541 switch (target_type.BuiltinType) {
542 case BuiltinTypeSpec.Type.Int:
543 case BuiltinTypeSpec.Type.UInt:
544 return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
545 case BuiltinTypeSpec.Type.ULong:
546 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
547 case BuiltinTypeSpec.Type.Long:
548 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
549 case BuiltinTypeSpec.Type.Double:
550 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
551 case BuiltinTypeSpec.Type.Float:
552 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
553 case BuiltinTypeSpec.Type.Decimal:
554 return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
557 case BuiltinTypeSpec.Type.Int:
559 // From int to long, float, double, decimal
561 switch (target_type.BuiltinType) {
562 case BuiltinTypeSpec.Type.Long:
563 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
564 case BuiltinTypeSpec.Type.Double:
565 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
566 case BuiltinTypeSpec.Type.Float:
567 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
568 case BuiltinTypeSpec.Type.Decimal:
569 return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
572 case BuiltinTypeSpec.Type.UInt:
574 // From uint to long, ulong, float, double, decimal
576 switch (target_type.BuiltinType) {
577 case BuiltinTypeSpec.Type.Long:
578 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
579 case BuiltinTypeSpec.Type.ULong:
580 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
581 case BuiltinTypeSpec.Type.Double:
582 return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
583 case BuiltinTypeSpec.Type.Float:
584 return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
585 case BuiltinTypeSpec.Type.Decimal:
586 return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
589 case BuiltinTypeSpec.Type.Long:
591 // From long to float, double, decimal
593 switch (target_type.BuiltinType) {
594 case BuiltinTypeSpec.Type.Double:
595 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
596 case BuiltinTypeSpec.Type.Float:
597 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
598 case BuiltinTypeSpec.Type.Decimal:
599 return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
602 case BuiltinTypeSpec.Type.ULong:
604 // From ulong to float, double, decimal
606 switch (target_type.BuiltinType) {
607 case BuiltinTypeSpec.Type.Double:
608 return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
609 case BuiltinTypeSpec.Type.Float:
610 return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
611 case BuiltinTypeSpec.Type.Decimal:
612 return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
615 case BuiltinTypeSpec.Type.Char:
617 // From char to ushort, int, uint, long, ulong, float, double, decimal
619 switch (target_type.BuiltinType) {
620 case BuiltinTypeSpec.Type.UShort:
621 case BuiltinTypeSpec.Type.Int:
622 case BuiltinTypeSpec.Type.UInt:
623 return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
624 case BuiltinTypeSpec.Type.ULong:
625 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
626 case BuiltinTypeSpec.Type.Long:
627 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
628 case BuiltinTypeSpec.Type.Float:
629 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
630 case BuiltinTypeSpec.Type.Double:
631 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
632 case BuiltinTypeSpec.Type.Decimal:
633 return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
636 case BuiltinTypeSpec.Type.Float:
640 if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
641 return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
649 // Full version of implicit conversion
651 public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type)
653 if (ImplicitStandardConversionExists (expr, target_type))
656 if (expr.Type == InternalType.AnonymousMethod) {
657 if (!target_type.IsDelegate && !target_type.IsExpressionTreeType)
660 AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
661 return ame.ImplicitStandardConversionExists (ec, target_type);
664 if (expr.eclass == ExprClass.MethodGroup) {
665 if (target_type.IsDelegate && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) {
666 MethodGroupExpr mg = expr as MethodGroupExpr;
668 return DelegateCreation.ImplicitStandardConversionExists (ec, mg, target_type);
674 // Conversion from __arglist to System.ArgIterator
675 if (expr.Type == InternalType.Arglist)
676 return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec;
678 return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null;
682 // Implicit standard conversion (only core conversions are used here)
684 public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type)
687 // Identity conversions
688 // Implicit numeric conversions
689 // Implicit nullable conversions
690 // Implicit reference conversions
691 // Boxing conversions
692 // Implicit constant expression conversions
693 // Implicit conversions involving type parameters
696 TypeSpec expr_type = expr.Type;
698 if (expr_type == target_type)
701 if (target_type.IsNullableType)
702 return ImplicitNulableConversion (null, expr, target_type) != null;
704 if (ImplicitNumericConversion (null, expr_type, target_type) != null)
707 if (ImplicitReferenceConversionExists (expr_type, target_type, false))
710 if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
714 // Implicit Constant Expression Conversions
716 if (expr is IntConstant){
717 int value = ((IntConstant) expr).Value;
718 switch (target_type.BuiltinType) {
719 case BuiltinTypeSpec.Type.SByte:
720 if (value >= SByte.MinValue && value <= SByte.MaxValue)
723 case BuiltinTypeSpec.Type.Byte:
724 if (value >= 0 && value <= Byte.MaxValue)
727 case BuiltinTypeSpec.Type.Short:
728 if (value >= Int16.MinValue && value <= Int16.MaxValue)
731 case BuiltinTypeSpec.Type.UShort:
732 if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
735 case BuiltinTypeSpec.Type.UInt:
739 case BuiltinTypeSpec.Type.ULong:
741 // we can optimize this case: a positive int32
742 // always fits on a uint64. But we need an opcode
752 if (expr is LongConstant && target_type.BuiltinType == BuiltinTypeSpec.Type.ULong){
754 // Try the implicit constant expression conversion
755 // from long to ulong, instead of a nice routine,
758 long v = ((LongConstant) expr).Value;
763 if (expr is IntegralConstant && target_type.IsEnum) {
764 var i = (IntegralConstant) expr;
766 // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
768 // An implicit enumeration conversion permits the decimal-integer-literal 0
769 // to be converted to any enum-type and to any nullable-type whose underlying
770 // type is an enum-type
772 return i.IsZeroInteger;
775 // Implicit dynamic conversion
776 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
777 switch (target_type.Kind) {
778 case MemberKind.ArrayType:
779 case MemberKind.Class:
780 case MemberKind.Struct:
781 case MemberKind.Delegate:
782 case MemberKind.Enum:
783 case MemberKind.Interface:
784 case MemberKind.TypeParameter:
788 // dynamic to __arglist
789 if (target_type == InternalType.Arglist)
796 // In an unsafe context implicit conversions is extended to include
798 // From any pointer-type to the type void*
799 // From the null literal to any pointer-type.
801 // LAMESPEC: The specification claims this conversion is allowed in implicit conversion but
802 // in reality implicit standard conversion uses it
804 if (target_type.IsPointer && expr.Type.IsPointer && ((PointerContainer) target_type).Element.Kind == MemberKind.Void)
808 // Struct identity conversion, including dynamic erasure
810 if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
817 /// Finds "most encompassed type" according to the spec (13.4.2)
818 /// amongst the methods in the MethodGroupExpr
820 public static TypeSpec FindMostEncompassedType (IEnumerable<TypeSpec> types)
822 TypeSpec best = null;
823 EmptyExpression expr;
825 foreach (TypeSpec t in types) {
831 expr = new EmptyExpression (t);
832 if (ImplicitStandardConversionExists (expr, best))
836 expr = new EmptyExpression (best);
837 foreach (TypeSpec t in types) {
840 if (!ImplicitStandardConversionExists (expr, t)) {
850 // Finds the most encompassing type (type into which all other
851 // types can convert to) amongst the types in the given set
853 static TypeSpec FindMostEncompassingType (IList<TypeSpec> types)
855 if (types.Count == 0)
858 if (types.Count == 1)
861 TypeSpec best = null;
862 for (int i = 0; i < types.Count; ++i) {
864 for (; ii < types.Count; ++ii) {
868 var expr = new EmptyExpression (types[ii]);
869 if (!ImplicitStandardConversionExists (expr, types [i])) {
883 // Indicates multiple best types
884 return InternalType.FakeInternalType;
891 // Finds the most specific source Sx according to the rules of the spec (13.4.4)
892 // by making use of FindMostEncomp* methods. Applies the correct rules separately
893 // for explicit and implicit conversion operators.
895 static TypeSpec FindMostSpecificSource (List<MethodSpec> list, TypeSpec sourceType, Expression source, bool apply_explicit_conv_rules)
897 var src_types_set = new TypeSpec [list.Count];
900 // Try exact match first, if any operator converts from S then Sx = S
902 for (int i = 0; i < src_types_set.Length; ++i) {
903 TypeSpec param_type = list [i].Parameters.Types [0];
905 if (param_type == sourceType)
908 src_types_set [i] = param_type;
912 // Explicit Conv rules
914 if (apply_explicit_conv_rules) {
915 var candidate_set = new List<TypeSpec> ();
917 foreach (TypeSpec param_type in src_types_set){
918 if (ImplicitStandardConversionExists (source, param_type))
919 candidate_set.Add (param_type);
922 if (candidate_set.Count != 0)
923 return FindMostEncompassedType (candidate_set);
929 if (apply_explicit_conv_rules)
930 return FindMostEncompassingType (src_types_set);
932 return FindMostEncompassedType (src_types_set);
936 /// Finds the most specific target Tx according to section 13.4.4
938 static public TypeSpec FindMostSpecificTarget (IList<MethodSpec> list,
939 TypeSpec target, bool apply_explicit_conv_rules)
941 var tgt_types_set = new List<TypeSpec> ();
944 // If any operator converts to T then Tx = T
946 foreach (var mi in list){
947 TypeSpec ret_type = mi.ReturnType;
948 if (ret_type == target)
951 tgt_types_set.Add (ret_type);
955 // Explicit conv rules
957 if (apply_explicit_conv_rules) {
958 var candidate_set = new List<TypeSpec> ();
960 foreach (TypeSpec ret_type in tgt_types_set) {
961 var expr = new EmptyExpression (ret_type);
963 if (ImplicitStandardConversionExists (expr, target))
964 candidate_set.Add (ret_type);
967 if (candidate_set.Count != 0)
968 return FindMostEncompassingType (candidate_set);
972 // Okay, final case !
974 if (apply_explicit_conv_rules)
975 return FindMostEncompassedType (tgt_types_set);
977 return FindMostEncompassingType (tgt_types_set);
981 /// User-defined Implicit conversions
983 static public Expression ImplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
985 return UserDefinedConversion (ec, source, target, true, loc);
989 /// User-defined Explicit conversions
991 static Expression ExplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
993 return UserDefinedConversion (ec, source, target, false, loc);
996 static void FindApplicableUserDefinedConversionOperators (IList<MemberSpec> operators, Expression source, TypeSpec target, bool implicitOnly, ref List<MethodSpec> candidates)
998 if (source.Type.IsInterface) {
999 // Neither A nor B are interface-types
1003 // For a conversion operator to be applicable, it must be possible
1004 // to perform a standard conversion from the source type to
1005 // the operand type of the operator, and it must be possible
1006 // to perform a standard conversion from the result type of
1007 // the operator to the target type.
1009 Expression texpr = null;
1011 foreach (MethodSpec op in operators) {
1013 // Can be null because MemberCache.GetUserOperator does not resize the array
1017 var t = op.Parameters.Types[0];
1018 if (source.Type != t && !ImplicitStandardConversionExists (source, t)) {
1022 if (!ImplicitStandardConversionExists (new EmptyExpression (t), source.Type))
1032 if (t.IsNullableType)
1033 t = Nullable.NullableInfo.GetUnderlyingType (t);
1035 if (!ImplicitStandardConversionExists (new EmptyExpression (t), target)) {
1040 texpr = new EmptyExpression (target);
1042 if (!ImplicitStandardConversionExists (texpr, t))
1047 if (candidates == null)
1048 candidates = new List<MethodSpec> ();
1050 candidates.Add (op);
1055 // User-defined conversions
1057 static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, Location loc)
1059 List<MethodSpec> candidates = null;
1062 // If S or T are nullable types, source_type and target_type are their underlying types
1063 // otherwise source_type and target_type are equal to S and T respectively.
1065 TypeSpec source_type = source.Type;
1066 TypeSpec target_type = target;
1067 Expression source_type_expr;
1069 if (source_type.IsNullableType) {
1070 // No implicit conversion S? -> T for non-reference types
1071 if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType)
1074 source_type_expr = Nullable.Unwrap.Create (source);
1075 source_type = source_type_expr.Type;
1077 source_type_expr = source;
1080 if (target_type.IsNullableType)
1081 target_type = Nullable.NullableInfo.GetUnderlyingType (target_type);
1083 // Only these containers can contain a user defined implicit or explicit operators
1084 const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter;
1086 if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1087 bool declared_only = source_type.IsStruct;
1089 var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only);
1090 if (operators != null) {
1091 FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1094 if (!implicitOnly) {
1095 operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only);
1096 if (operators != null) {
1097 FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1102 if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1103 bool declared_only = target.IsStruct || implicitOnly;
1105 var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only);
1106 if (operators != null) {
1107 FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1110 if (!implicitOnly) {
1111 operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only);
1112 if (operators != null) {
1113 FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1118 if (candidates == null)
1122 // Find the most specific conversion operator
1124 MethodSpec most_specific_operator;
1126 if (candidates.Count == 1) {
1127 most_specific_operator = candidates[0];
1128 s_x = most_specific_operator.Parameters.Types[0];
1129 t_x = most_specific_operator.ReturnType;
1132 // Pass original source type to find the best match against input type and
1133 // not the unwrapped expression
1135 s_x = FindMostSpecificSource (candidates, source.Type, source_type_expr, !implicitOnly);
1139 t_x = FindMostSpecificTarget (candidates, target, !implicitOnly);
1143 most_specific_operator = null;
1144 for (int i = 0; i < candidates.Count; ++i) {
1145 if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) {
1146 most_specific_operator = candidates[i];
1151 if (most_specific_operator == null) {
1152 MethodSpec ambig_arg = null;
1153 foreach (var candidate in candidates) {
1154 if (candidate.ReturnType == t_x)
1155 most_specific_operator = candidate;
1156 else if (candidate.Parameters.Types[0] == s_x)
1157 ambig_arg = candidate;
1160 ec.Report.Error (457, loc,
1161 "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'",
1162 ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (),
1163 source.Type.GetSignatureForError (), target.GetSignatureForError ());
1165 return ErrorExpression.Instance;
1170 // Convert input type when it's different to best operator argument
1172 if (s_x != source_type) {
1173 var c = source as Constant;
1175 source = c.TryReduce (ec, s_x, loc);
1177 source = implicitOnly ?
1178 ImplicitConversionStandard (ec, source_type_expr, s_x, loc) :
1179 ExplicitConversionStandard (ec, source_type_expr, s_x, loc);
1182 source = source_type_expr;
1185 source = new UserCast (most_specific_operator, source, loc).Resolve (ec);
1188 // Convert result type when it's different to best operator return type
1190 if (t_x != target_type) {
1192 // User operator is of T?, no need to lift it
1194 if (t_x == target && t_x.IsNullableType)
1197 source = implicitOnly ?
1198 ImplicitConversionStandard (ec, source, target_type, loc) :
1199 ExplicitConversionStandard (ec, source, target_type, loc);
1206 // Source expression is of nullable type, lift the result in the case it's null and
1207 // not nullable/lifted user operator is used
1209 if (source_type_expr is Nullable.Unwrap && !s_x.IsNullableType && (TypeSpec.IsReferenceType (target) || target_type != target))
1210 source = new Nullable.Lifted (source, source_type_expr, target).Resolve (ec);
1211 else if (target_type != target)
1212 source = Nullable.Wrap.Create (source, target);
1218 /// Converts implicitly the resolved expression `expr' into the
1219 /// `target_type'. It returns a new expression that can be used
1220 /// in a context that expects a `target_type'.
1222 static public Expression ImplicitConversion (ResolveContext ec, Expression expr,
1223 TypeSpec target_type, Location loc)
1227 if (target_type == null)
1228 throw new Exception ("Target type is null");
1230 e = ImplicitConversionStandard (ec, expr, target_type, loc);
1234 e = ImplicitUserConversion (ec, expr, target_type, loc);
1243 /// Attempts to apply the `Standard Implicit
1244 /// Conversion' rules to the expression `expr' into
1245 /// the `target_type'. It returns a new expression
1246 /// that can be used in a context that expects a
1249 /// This is different from `ImplicitConversion' in that the
1250 /// user defined implicit conversions are excluded.
1252 static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr,
1253 TypeSpec target_type, Location loc)
1255 return ImplicitConversionStandard (ec, expr, target_type, loc, false);
1258 static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast)
1260 if (expr.eclass == ExprClass.MethodGroup){
1261 if (!TypeManager.IsDelegateType (target_type)){
1266 // Only allow anonymous method conversions on post ISO_1
1268 if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){
1269 MethodGroupExpr mg = expr as MethodGroupExpr;
1271 return ImplicitDelegateCreation.Create (
1272 ec, mg, target_type, loc);
1276 TypeSpec expr_type = expr.Type;
1279 if (expr_type == target_type) {
1280 if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod)
1285 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1286 switch (target_type.Kind) {
1287 case MemberKind.ArrayType:
1288 case MemberKind.Class:
1289 if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object)
1290 return EmptyCast.Create (expr, target_type);
1292 goto case MemberKind.Struct;
1293 case MemberKind.Struct:
1294 case MemberKind.Delegate:
1295 case MemberKind.Enum:
1296 case MemberKind.Interface:
1297 case MemberKind.TypeParameter:
1298 Arguments args = new Arguments (1);
1299 args.Add (new Argument (expr));
1300 return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec);
1306 if (target_type.IsNullableType)
1307 return ImplicitNulableConversion (ec, expr, target_type);
1310 // Attempt to do the implicit constant expression conversions
1312 Constant c = expr as Constant;
1315 c = c.ConvertImplicitly (target_type);
1317 Console.WriteLine ("Conversion error happened in line {0}", loc);
1324 e = ImplicitNumericConversion (expr, expr_type, target_type);
1328 e = ImplicitReferenceConversion (expr, target_type, explicit_cast);
1332 e = ImplicitBoxingConversion (expr, expr_type, target_type);
1336 if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)){
1337 var i = (IntegralConstant) expr;
1339 // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
1341 // An implicit enumeration conversion permits the decimal-integer-literal 0
1342 // to be converted to any enum-type and to any nullable-type whose underlying
1343 // type is an enum-type
1345 if (i.IsZeroInteger) {
1346 // Recreate 0 literal to remove any collected conversions
1347 return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type);
1352 var target_pc = target_type as PointerContainer;
1353 if (target_pc != null) {
1354 if (expr_type.IsPointer) {
1356 // Pointer types are same when they have same element types
1358 if (expr_type == target_pc)
1361 if (target_pc.Element.Kind == MemberKind.Void)
1362 return EmptyCast.Create (expr, target_type);
1367 if (expr_type == InternalType.NullLiteral)
1368 return new NullPointer (target_type, loc);
1372 if (expr_type == InternalType.AnonymousMethod){
1373 AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
1374 Expression am = ame.Compatible (ec, target_type);
1376 return am.Resolve (ec);
1379 if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec)
1383 // dynamic erasure conversion on value types
1385 if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
1386 return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type);
1392 /// Attempts to implicitly convert `source' into `target_type', using
1393 /// ImplicitConversion. If there is no implicit conversion, then
1394 /// an error is signaled
1396 static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
1397 TypeSpec target_type, Location loc)
1399 Expression e = ImplicitConversion (ec, source, target_type, loc);
1403 source.Error_ValueCannotBeConverted (ec, loc, target_type, false);
1408 /// Performs the explicit numeric conversions
1410 /// There are a few conversions that are not part of the C# standard,
1411 /// they were interim hacks in the C# compiler that were supposed to
1412 /// become explicit operators in the UIntPtr class and IntPtr class,
1413 /// but for historical reasons it did not happen, so the C# compiler
1414 /// ended up with these special hacks.
1416 /// See bug 59800 for details.
1418 /// The conversion are:
1428 public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type)
1430 // Not all predefined explicit numeric conversion are
1431 // defined here, for some of them (mostly IntPtr/UIntPtr) we
1432 // defer to user-operator handling which is now perfect but
1435 // LAMESPEC: Undocumented IntPtr/UIntPtr conversions
1436 // IntPtr -> uint uses int
1437 // UIntPtr -> long uses ulong
1440 switch (expr.Type.BuiltinType) {
1441 case BuiltinTypeSpec.Type.SByte:
1443 // From sbyte to byte, ushort, uint, ulong, char, uintptr
1445 switch (target_type.BuiltinType) {
1446 case BuiltinTypeSpec.Type.Byte:
1447 return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
1448 case BuiltinTypeSpec.Type.UShort:
1449 return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
1450 case BuiltinTypeSpec.Type.UInt:
1451 return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
1452 case BuiltinTypeSpec.Type.ULong:
1453 return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
1454 case BuiltinTypeSpec.Type.Char:
1455 return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
1457 // One of the built-in conversions that belonged in the class library
1458 case BuiltinTypeSpec.Type.UIntPtr:
1459 return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true);
1462 case BuiltinTypeSpec.Type.Byte:
1464 // From byte to sbyte and char
1466 switch (target_type.BuiltinType) {
1467 case BuiltinTypeSpec.Type.SByte:
1468 return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
1469 case BuiltinTypeSpec.Type.Char:
1470 return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
1473 case BuiltinTypeSpec.Type.Short:
1475 // From short to sbyte, byte, ushort, uint, ulong, char, uintptr
1477 switch (target_type.BuiltinType) {
1478 case BuiltinTypeSpec.Type.SByte:
1479 return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
1480 case BuiltinTypeSpec.Type.Byte:
1481 return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
1482 case BuiltinTypeSpec.Type.UShort:
1483 return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
1484 case BuiltinTypeSpec.Type.UInt:
1485 return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
1486 case BuiltinTypeSpec.Type.ULong:
1487 return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
1488 case BuiltinTypeSpec.Type.Char:
1489 return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
1491 // One of the built-in conversions that belonged in the class library
1492 case BuiltinTypeSpec.Type.UIntPtr:
1493 return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1496 case BuiltinTypeSpec.Type.UShort:
1498 // From ushort to sbyte, byte, short, char
1500 switch (target_type.BuiltinType) {
1501 case BuiltinTypeSpec.Type.SByte:
1502 return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
1503 case BuiltinTypeSpec.Type.Byte:
1504 return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
1505 case BuiltinTypeSpec.Type.Short:
1506 return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
1507 case BuiltinTypeSpec.Type.Char:
1508 return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
1511 case BuiltinTypeSpec.Type.Int:
1513 // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
1515 switch (target_type.BuiltinType) {
1516 case BuiltinTypeSpec.Type.SByte:
1517 return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
1518 case BuiltinTypeSpec.Type.Byte:
1519 return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
1520 case BuiltinTypeSpec.Type.Short:
1521 return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
1522 case BuiltinTypeSpec.Type.UShort:
1523 return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
1524 case BuiltinTypeSpec.Type.UInt:
1525 return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
1526 case BuiltinTypeSpec.Type.ULong:
1527 return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
1528 case BuiltinTypeSpec.Type.Char:
1529 return new ConvCast (expr, target_type, ConvCast.Mode.I4_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.UInt:
1538 // From uint to sbyte, byte, short, ushort, int, char
1540 switch (target_type.BuiltinType) {
1541 case BuiltinTypeSpec.Type.SByte:
1542 return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
1543 case BuiltinTypeSpec.Type.Byte:
1544 return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
1545 case BuiltinTypeSpec.Type.Short:
1546 return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
1547 case BuiltinTypeSpec.Type.UShort:
1548 return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
1549 case BuiltinTypeSpec.Type.Int:
1550 return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
1551 case BuiltinTypeSpec.Type.Char:
1552 return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
1555 case BuiltinTypeSpec.Type.Long:
1557 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1559 switch (target_type.BuiltinType) {
1560 case BuiltinTypeSpec.Type.SByte:
1561 return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
1562 case BuiltinTypeSpec.Type.Byte:
1563 return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
1564 case BuiltinTypeSpec.Type.Short:
1565 return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
1566 case BuiltinTypeSpec.Type.UShort:
1567 return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
1568 case BuiltinTypeSpec.Type.Int:
1569 return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
1570 case BuiltinTypeSpec.Type.UInt:
1571 return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
1572 case BuiltinTypeSpec.Type.ULong:
1573 return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
1574 case BuiltinTypeSpec.Type.Char:
1575 return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
1578 case BuiltinTypeSpec.Type.ULong:
1580 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1582 switch (target_type.BuiltinType) {
1583 case BuiltinTypeSpec.Type.SByte:
1584 return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
1585 case BuiltinTypeSpec.Type.Byte:
1586 return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
1587 case BuiltinTypeSpec.Type.Short:
1588 return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
1589 case BuiltinTypeSpec.Type.UShort:
1590 return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
1591 case BuiltinTypeSpec.Type.Int:
1592 return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
1593 case BuiltinTypeSpec.Type.UInt:
1594 return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
1595 case BuiltinTypeSpec.Type.Long:
1596 return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
1597 case BuiltinTypeSpec.Type.Char:
1598 return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
1600 // One of the built-in conversions that belonged in the class library
1601 case BuiltinTypeSpec.Type.IntPtr:
1602 return new OperatorCast (EmptyCast.Create (expr, rc.BuiltinTypes.Long), target_type, true);
1605 case BuiltinTypeSpec.Type.Char:
1607 // From char to sbyte, byte, short
1609 switch (target_type.BuiltinType) {
1610 case BuiltinTypeSpec.Type.SByte:
1611 return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
1612 case BuiltinTypeSpec.Type.Byte:
1613 return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
1614 case BuiltinTypeSpec.Type.Short:
1615 return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
1618 case BuiltinTypeSpec.Type.Float:
1620 // From float to sbyte, byte, short,
1621 // ushort, int, uint, long, ulong, char
1624 switch (target_type.BuiltinType) {
1625 case BuiltinTypeSpec.Type.SByte:
1626 return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
1627 case BuiltinTypeSpec.Type.Byte:
1628 return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
1629 case BuiltinTypeSpec.Type.Short:
1630 return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
1631 case BuiltinTypeSpec.Type.UShort:
1632 return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
1633 case BuiltinTypeSpec.Type.Int:
1634 return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
1635 case BuiltinTypeSpec.Type.UInt:
1636 return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
1637 case BuiltinTypeSpec.Type.Long:
1638 return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
1639 case BuiltinTypeSpec.Type.ULong:
1640 return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
1641 case BuiltinTypeSpec.Type.Char:
1642 return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
1643 case BuiltinTypeSpec.Type.Decimal:
1644 return new OperatorCast (expr, target_type, true);
1647 case BuiltinTypeSpec.Type.Double:
1649 // From double to sbyte, byte, short,
1650 // ushort, int, uint, long, ulong,
1651 // char, float or decimal
1653 switch (target_type.BuiltinType) {
1654 case BuiltinTypeSpec.Type.SByte:
1655 return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
1656 case BuiltinTypeSpec.Type.Byte:
1657 return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
1658 case BuiltinTypeSpec.Type.Short:
1659 return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
1660 case BuiltinTypeSpec.Type.UShort:
1661 return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
1662 case BuiltinTypeSpec.Type.Int:
1663 return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
1664 case BuiltinTypeSpec.Type.UInt:
1665 return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
1666 case BuiltinTypeSpec.Type.Long:
1667 return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
1668 case BuiltinTypeSpec.Type.ULong:
1669 return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
1670 case BuiltinTypeSpec.Type.Char:
1671 return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
1672 case BuiltinTypeSpec.Type.Float:
1673 return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
1674 case BuiltinTypeSpec.Type.Decimal:
1675 return new OperatorCast (expr, target_type, true);
1678 case BuiltinTypeSpec.Type.UIntPtr:
1680 // Various built-in conversions that belonged in the class library
1682 // from uintptr to sbyte, short, int32
1684 switch (target_type.BuiltinType) {
1685 case BuiltinTypeSpec.Type.SByte:
1686 return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I1);
1687 case BuiltinTypeSpec.Type.Short:
1688 return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I2);
1689 case BuiltinTypeSpec.Type.Int:
1690 return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type);
1691 case BuiltinTypeSpec.Type.UInt:
1692 return new OperatorCast (expr, expr.Type, target_type, true);
1693 case BuiltinTypeSpec.Type.Long:
1694 return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.ULong, true), target_type);
1697 case BuiltinTypeSpec.Type.IntPtr:
1698 if (target_type.BuiltinType == BuiltinTypeSpec.Type.UInt)
1699 return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Int, true), target_type);
1700 if (target_type.BuiltinType == BuiltinTypeSpec.Type.ULong)
1701 return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Long, true), target_type);
1704 case BuiltinTypeSpec.Type.Decimal:
1705 // From decimal to sbyte, byte, short,
1706 // ushort, int, uint, long, ulong, char,
1708 switch (target_type.BuiltinType) {
1709 case BuiltinTypeSpec.Type.SByte:
1710 case BuiltinTypeSpec.Type.Byte:
1711 case BuiltinTypeSpec.Type.Short:
1712 case BuiltinTypeSpec.Type.UShort:
1713 case BuiltinTypeSpec.Type.Int:
1714 case BuiltinTypeSpec.Type.UInt:
1715 case BuiltinTypeSpec.Type.Long:
1716 case BuiltinTypeSpec.Type.ULong:
1717 case BuiltinTypeSpec.Type.Char:
1718 case BuiltinTypeSpec.Type.Float:
1719 case BuiltinTypeSpec.Type.Double:
1720 return new OperatorCast (expr, expr.Type, target_type, true);
1730 /// Returns whether an explicit reference conversion can be performed
1731 /// from source_type to target_type
1733 public static bool ExplicitReferenceConversionExists (TypeSpec source_type, TypeSpec target_type)
1735 Expression e = ExplicitReferenceConversion (null, source_type, target_type);
1739 if (e == EmptyExpression.Null)
1742 throw new InternalErrorException ("Invalid probing conversion result");
1746 /// Implements Explicit Reference conversions
1748 static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
1751 // From object to a generic parameter
1753 if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type))
1754 return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1757 // Explicit type parameter conversion.
1759 if (source_type.Kind == MemberKind.TypeParameter)
1760 return ExplicitTypeParameterConversion (source, source_type, target_type);
1762 bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum;
1765 // Unboxing conversion from System.ValueType to any non-nullable-value-type
1767 if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type)
1768 return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1771 // From object or dynamic to any reference type or value type (unboxing)
1773 if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1774 if (target_type.IsPointer)
1778 source == null ? EmptyExpression.Null :
1779 target_is_value_type ? new UnboxCast (source, target_type) :
1780 source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) :
1781 new ClassCast (source, target_type);
1785 // From any class S to any class-type T, provided S is a base class of T
1787 if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true))
1788 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1791 // From any interface-type S to to any class type T, provided T is not
1792 // sealed, or provided T implements S.
1794 if (source_type.Kind == MemberKind.Interface) {
1795 if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) {
1797 return EmptyExpression.Null;
1800 // Unboxing conversion from any interface-type to any non-nullable-value-type that
1801 // implements the interface-type
1803 return target_is_value_type ? new UnboxCast (source, target_type) : (Expression) new ClassCast (source, target_type);
1807 // From System.Collections.Generic.IList<T> and its base interfaces to a one-dimensional
1808 // array type S[], provided there is an implicit or explicit reference conversion from S to T.
1810 var target_array = target_type as ArrayContainer;
1811 if (target_array != null && IList_To_Array (source_type, target_array))
1812 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1817 var source_array = source_type as ArrayContainer;
1818 if (source_array != null) {
1819 var target_array = target_type as ArrayContainer;
1820 if (target_array != null) {
1822 // From System.Array to any array-type
1824 if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array)
1825 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1828 // From an array type S with an element type Se to an array type T with an
1829 // element type Te provided all the following are true:
1830 // * S and T differe only in element type, in other words, S and T
1831 // have the same number of dimensions.
1832 // * Both Se and Te are reference types
1833 // * An explicit reference conversions exist from Se to Te
1835 if (source_array.Rank == target_array.Rank) {
1837 source_type = source_array.Element;
1838 if (!TypeSpec.IsReferenceType (source_type))
1841 var target_element = target_array.Element;
1842 if (!TypeSpec.IsReferenceType (target_element))
1845 if (ExplicitReferenceConversionExists (source_type, target_element))
1846 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1853 // From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces,
1854 // provided that there is an explicit reference conversion from S to T
1856 if (ArrayToIList (source_array, target_type, true))
1857 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1863 // From any class type S to any interface T, provides S is not sealed
1864 // and provided S does not implement T.
1866 if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type, true)) {
1867 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1871 // From System delegate to any delegate-type
1873 if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && TypeManager.IsDelegateType (target_type))
1874 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1877 // From variant generic delegate to same variant generic delegate type
1879 if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) {
1880 var tparams = source_type.MemberDefinition.TypeParameters;
1881 var targs_src = source_type.TypeArguments;
1882 var targs_dst = target_type.TypeArguments;
1884 for (i = 0; i < tparams.Length; ++i) {
1886 // If TP is invariant, types have to be identical
1888 if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i]))
1891 if (tparams[i].Variance == Variance.Covariant) {
1893 //If TP is covariant, an implicit or explicit identity or reference conversion is required
1895 if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1898 if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1901 } else if (tparams[i].Variance == Variance.Contravariant) {
1903 //If TP is contravariant, both are either identical or reference types
1905 if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i]))
1912 if (i == tparams.Length)
1913 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1920 /// Performs an explicit conversion of the expression `expr' whose
1921 /// type is expr.Type to `target_type'.
1923 static public Expression ExplicitConversionCore (ResolveContext ec, Expression expr,
1924 TypeSpec target_type, Location loc)
1926 TypeSpec expr_type = expr.Type;
1928 // Explicit conversion includes implicit conversion and it used for enum underlying types too
1929 Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true);
1933 if (TypeManager.IsEnumType (expr_type)) {
1934 TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1935 Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type));
1936 if (underlying.Type == real_target)
1940 ne = ImplicitNumericConversion (underlying, real_target);
1943 ne = ExplicitNumericConversion (ec, underlying, real_target);
1946 // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
1948 if (ne == null && (real_target.BuiltinType == BuiltinTypeSpec.Type.IntPtr || real_target.BuiltinType == BuiltinTypeSpec.Type.UIntPtr))
1949 ne = ExplicitUserConversion (ec, underlying, real_target, loc);
1951 return ne != null ? EmptyCast.Create (ne, target_type) : null;
1954 if (TypeManager.IsEnumType (target_type)) {
1956 // System.Enum can be unboxed to any enum-type
1958 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Enum)
1959 return new UnboxCast (expr, target_type);
1961 TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1963 if (expr_type == real_target)
1964 return EmptyCast.Create (expr, target_type);
1966 ne = ImplicitNumericConversion (expr, real_target);
1968 return EmptyCast.Create (ne, target_type);
1970 ne = ExplicitNumericConversion (ec, expr, real_target);
1972 return EmptyCast.Create (ne, target_type);
1975 // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
1977 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.IntPtr || expr_type.BuiltinType == BuiltinTypeSpec.Type.UIntPtr) {
1978 ne = ExplicitUserConversion (ec, expr, real_target, loc);
1980 return ExplicitConversionCore (ec, ne, target_type, loc);
1983 ne = ExplicitNumericConversion (ec, expr, target_type);
1989 // Skip the ExplicitReferenceConversion because we can not convert
1990 // from Null to a ValueType, and ExplicitReference wont check against
1991 // null literal explicitly
1993 if (expr_type != InternalType.NullLiteral) {
1994 ne = ExplicitReferenceConversion (expr, expr_type, target_type);
2000 ne = ExplicitUnsafe (expr, target_type);
2008 public static Expression ExplicitUnsafe (Expression expr, TypeSpec target_type)
2010 TypeSpec expr_type = expr.Type;
2012 if (target_type.IsPointer){
2013 if (expr_type.IsPointer)
2014 return EmptyCast.Create (expr, target_type);
2016 switch (expr_type.BuiltinType) {
2017 case BuiltinTypeSpec.Type.SByte:
2018 case BuiltinTypeSpec.Type.Short:
2019 case BuiltinTypeSpec.Type.Int:
2020 return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
2022 case BuiltinTypeSpec.Type.UShort:
2023 case BuiltinTypeSpec.Type.UInt:
2024 case BuiltinTypeSpec.Type.Byte:
2025 return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2027 case BuiltinTypeSpec.Type.Long:
2028 return new ConvCast (expr, target_type, ConvCast.Mode.I8_I);
2030 case BuiltinTypeSpec.Type.ULong:
2031 return new ConvCast (expr, target_type, ConvCast.Mode.U8_I);
2035 if (expr_type.IsPointer){
2036 switch (target_type.BuiltinType) {
2037 case BuiltinTypeSpec.Type.SByte:
2038 return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
2039 case BuiltinTypeSpec.Type.Byte:
2040 return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
2041 case BuiltinTypeSpec.Type.Short:
2042 return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
2043 case BuiltinTypeSpec.Type.UShort:
2044 return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
2045 case BuiltinTypeSpec.Type.Int:
2046 return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
2047 case BuiltinTypeSpec.Type.UInt:
2048 return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
2049 case BuiltinTypeSpec.Type.Long:
2050 return new ConvCast (expr, target_type, ConvCast.Mode.I_I8);
2051 case BuiltinTypeSpec.Type.ULong:
2052 return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
2059 /// Same as ExplicitConversion, only it doesn't include user defined conversions
2061 static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr,
2062 TypeSpec target_type, Location l)
2064 int errors = ec.Report.Errors;
2065 Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
2066 if (ec.Report.Errors > errors)
2072 ne = ExplicitNumericConversion (ec, expr, target_type);
2076 ne = ExplicitReferenceConversion (expr, expr.Type, target_type);
2080 if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void)
2081 return EmptyCast.Create (expr, target_type);
2083 expr.Error_ValueCannotBeConverted (ec, l, target_type, true);
2088 /// Performs an explicit conversion of the expression `expr' whose
2089 /// type is expr.Type to `target_type'.
2091 static public Expression ExplicitConversion (ResolveContext ec, Expression expr,
2092 TypeSpec target_type, Location loc)
2094 Expression e = ExplicitConversionCore (ec, expr, target_type, loc);
2097 // Don't eliminate explicit precission casts
2100 if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float)
2101 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
2103 if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
2104 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
2110 TypeSpec expr_type = expr.Type;
2111 if (target_type.IsNullableType) {
2114 if (expr_type.IsNullableType) {
2115 target = Nullable.NullableInfo.GetUnderlyingType (target_type);
2116 Expression unwrap = Nullable.Unwrap.Create (expr);
2117 e = ExplicitConversion (ec, unwrap, target, expr.Location);
2121 return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec);
2123 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2124 return new UnboxCast (expr, target_type);
2127 target = TypeManager.GetTypeArguments (target_type) [0];
2128 e = ExplicitConversionCore (ec, expr, target, loc);
2130 return Nullable.Wrap.Create (e, target_type);
2131 } else if (expr_type.IsNullableType) {
2132 e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
2136 e = Nullable.Unwrap.Create (expr, false);
2137 e = ExplicitConversionCore (ec, e, target_type, loc);
2139 return EmptyCast.Create (e, target_type);
2142 e = ExplicitUserConversion (ec, expr, target_type, loc);
2146 expr.Error_ValueCannotBeConverted (ec, loc, target_type, true);