Merge pull request #952 from ermshiperete/bug-xamarin-2912
[mono.git] / mcs / mcs / convert.cs
1 //
2 // conversion.cs: various routines for implementing conversions.
3 //
4 // Authors:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Ravi Pratap (ravi@ximian.com)
7 //   Marek Safar (marek.safar@gmail.com)
8 //
9 // Copyright 2001, 2002, 2003 Ximian, Inc.
10 // Copyright 2003-2008 Novell, Inc.
11 // Copyright 2011 Xamarin Inc (http://www.xamarin.com)
12 //
13
14 using System;
15 using System.Collections.Generic;
16
17 #if STATIC
18 using IKVM.Reflection.Emit;
19 #else
20 using System.Reflection.Emit;
21 #endif
22
23 namespace Mono.CSharp {
24
25         //
26         // A container class for all the conversion operations
27         //
28         static class Convert
29         {
30                 //
31                 // From a one-dimensional array-type S[] to System.Collections.IList<T> and base
32                 // interfaces of this interface, provided there is an implicit reference conversion
33                 // from S to T.
34                 //
35                 static bool ArrayToIList (ArrayContainer array, TypeSpec list, bool isExplicit)
36                 {
37                         if (array.Rank != 1 || !list.IsArrayGenericInterface)
38                                 return false;
39
40                         var arg_type = list.TypeArguments[0];
41                         if (array.Element == arg_type)
42                                 return true;
43
44                         //
45                         // Reject conversion from T[] to IList<U> even if T has U dependency
46                         //
47                         if (arg_type.IsGenericParameter)
48                                 return false;
49
50                         if (isExplicit)
51                                 return ExplicitReferenceConversionExists (array.Element, arg_type);
52
53                         return ImplicitReferenceConversionExists (array.Element, arg_type);
54                 }
55                 
56                 static bool IList_To_Array(TypeSpec list, ArrayContainer array)
57                 {
58                         if (array.Rank != 1 || !list.IsArrayGenericInterface)
59                                 return false;
60
61                         var arg_type = list.TypeArguments[0];
62                         if (array.Element == arg_type)
63                                 return true;
64                         
65                         return ImplicitReferenceConversionExists (array.Element, arg_type) || ExplicitReferenceConversionExists (array.Element, arg_type);
66                 }
67
68                 public static Expression ImplicitTypeParameterConversion (Expression expr, TypeParameterSpec expr_type, TypeSpec target_type)
69                 {
70                         //
71                         // From T to a type parameter U, provided T depends on U
72                         //
73                         if (target_type.IsGenericParameter) {
74                                 if (expr_type.TypeArguments != null && expr_type.HasDependencyOn (target_type)) {
75                                         if (expr == null)
76                                                 return EmptyExpression.Null;
77
78                                         if (expr_type.IsReferenceType && !((TypeParameterSpec) target_type).IsReferenceType)
79                                                 return new BoxedCast (expr, target_type);
80
81                                         return new ClassCast (expr, target_type);
82                                 }
83
84                                 return null;
85                         }
86
87                         //
88                         // LAMESPEC: From T to dynamic type because it's like T to object
89                         //
90                         if (target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
91                                 if (expr == null)
92                                         return EmptyExpression.Null;
93
94                                 if (expr_type.IsReferenceType)
95                                         return new ClassCast (expr, target_type);
96
97                                 return new BoxedCast (expr, target_type);
98                         }
99
100                         //
101                         // From T to its effective base class C
102                         // From T to any base class of C (it cannot contain dynamic or be of dynamic type)
103                         // From T to any interface implemented by C
104                         //
105                         var base_type = expr_type.GetEffectiveBase ();
106                         if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type, true)) {
107                                 if (expr == null)
108                                         return EmptyExpression.Null;
109
110                                 if (expr_type.IsReferenceType)
111                                         return new ClassCast (expr, target_type);
112
113                                 return new BoxedCast (expr, target_type);
114                         }
115
116                         if (target_type.IsInterface && expr_type.IsConvertibleToInterface (target_type)) {
117                                 if (expr == null)
118                                         return EmptyExpression.Null;
119
120                                 if (expr_type.IsReferenceType)
121                                         return new ClassCast (expr, target_type);
122
123                                 return new BoxedCast (expr, target_type);
124                         }
125
126                         return null;
127                 }
128
129                 static Expression ExplicitTypeParameterConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
130                 {
131                         var target_tp = target_type as TypeParameterSpec;
132                         if (target_tp != null) {
133                                 if (target_tp.TypeArguments != null && target_tp.HasDependencyOn (source_type)) {
134                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
135                                 }
136
137 /*
138                                 if (target_tp.Interfaces != null) {
139                                         foreach (TypeSpec iface in target_tp.Interfaces) {
140                                                 if (!TypeManager.IsGenericParameter (iface))
141                                                         continue;
142
143                                                 if (TypeManager.IsSubclassOf (source_type, iface))
144                                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
145                                         }
146                                 }
147 */
148                                 return null;
149                         }
150
151                         if (target_type.IsInterface)
152                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
153
154                         return null;
155                 }
156
157                 public static Expression ImplicitReferenceConversion (Expression expr, TypeSpec target_type, bool explicit_cast)
158                 {
159                         TypeSpec expr_type = expr.Type;
160
161                         if (expr_type.Kind == MemberKind.TypeParameter)
162                                 return ImplicitTypeParameterConversion (expr, (TypeParameterSpec) expr.Type, target_type);
163
164                         //
165                         // from the null type to any reference-type.
166                         //
167                         NullLiteral nl = expr as NullLiteral;
168                         if (nl != null) {
169                                 return nl.ConvertImplicitly (target_type);
170                         }
171
172                         if (ImplicitReferenceConversionExists (expr_type, target_type)) {
173                                 // 
174                                 // Avoid wrapping implicitly convertible reference type
175                                 //
176                                 if (!explicit_cast)
177                                         return expr;
178
179                                 return EmptyCast.Create (expr, target_type);
180                         }
181
182                         return null;
183                 }
184
185                 //
186                 // Implicit reference conversions
187                 //
188                 public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type)
189                 {
190                         return ImplicitReferenceConversionExists (expr_type, target_type, true);
191                 }
192
193                 public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter)
194                 {
195                         // It's here only to speed things up
196                         if (target_type.IsStruct)
197                                 return false;
198
199                         switch (expr_type.Kind) {
200                         case MemberKind.TypeParameter:
201                                 return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null &&
202                                         (!refOnlyTypeParameter || TypeSpec.IsReferenceType (expr_type));
203
204                         case MemberKind.Class:
205                                 //
206                                 // From any class-type to dynamic (+object to speed up common path)
207                                 //
208                                 if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
209                                         return true;
210
211                                 if (target_type.IsClass) {
212                                         //
213                                         // Identity conversion, including dynamic erasure
214                                         //
215                                         if (TypeSpecComparer.IsEqual (expr_type, target_type))
216                                                 return true;
217
218                                         //
219                                         // From any class-type S to any class-type T, provided S is derived from T
220                                         //
221                                         return TypeSpec.IsBaseClass (expr_type, target_type, true);
222                                 }
223
224                                 //
225                                 // From any class-type S to any interface-type T, provided S implements T
226                                 //
227                                 if (target_type.IsInterface)
228                                         return expr_type.ImplementsInterface (target_type, true);
229
230                                 return false;
231
232                         case MemberKind.ArrayType:
233                                 //
234                                 // Identity array conversion
235                                 //
236                                 if (expr_type == target_type)
237                                         return true;
238
239                                 //
240                                 // From any array-type to System.Array
241                                 //
242                                 switch (target_type.BuiltinType) {
243                                 case BuiltinTypeSpec.Type.Array:
244                                 case BuiltinTypeSpec.Type.Object:
245                                 case BuiltinTypeSpec.Type.Dynamic:
246                                         return true;
247                                 }
248
249                                 var expr_type_array = (ArrayContainer) expr_type;
250                                 var target_type_array = target_type as ArrayContainer;
251
252                                 //
253                                 // From an array-type S to an array-type of type T
254                                 //
255                                 if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) {
256
257                                         //
258                                         // Both SE and TE are reference-types. TE check is defered
259                                         // to ImplicitReferenceConversionExists
260                                         //
261                                         TypeSpec expr_element_type = expr_type_array.Element;
262                                         if (!TypeSpec.IsReferenceType (expr_element_type))
263                                                 return false;
264
265                                         //
266                                         // An implicit reference conversion exists from SE to TE
267                                         //
268                                         return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element);
269                                 }
270
271                                 //
272                                 // From any array-type to the interfaces it implements
273                                 //
274                                 if (target_type.IsInterface) {
275                                         if (expr_type.ImplementsInterface (target_type, false))
276                                                 return true;
277
278                                         // from an array-type of type T to IList<T>
279                                         if (ArrayToIList (expr_type_array, target_type, false))
280                                                 return true;
281                                 }
282
283                                 return false;
284
285                         case MemberKind.Delegate:
286                                 //
287                                 // From any delegate-type to System.Delegate (and its base types)
288                                 //
289                                 switch (target_type.BuiltinType) {
290                                 case BuiltinTypeSpec.Type.Delegate:
291                                 case BuiltinTypeSpec.Type.MulticastDelegate:
292                                 case BuiltinTypeSpec.Type.Object:
293                                 case BuiltinTypeSpec.Type.Dynamic:
294                                         return true;
295                                 }
296
297                                 //
298                                 // Identity conversion, including dynamic erasure
299                                 //
300                                 if (TypeSpecComparer.IsEqual (expr_type, target_type))
301                                         return true;
302
303                                 //
304                                 // From any delegate-type to the interfaces it implements
305                                 // From any reference-type to an delegate type if is variance-convertible
306                                 //
307                                 return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type);
308
309                         case MemberKind.Interface:
310                                 //
311                                 // Identity conversion, including dynamic erasure
312                                 //
313                                 if (TypeSpecComparer.IsEqual (expr_type, target_type))
314                                         return true;
315
316                                 //
317                                 // From any interface type S to interface-type T
318                                 // From any reference-type to an interface if is variance-convertible
319                                 //
320                                 if (target_type.IsInterface)
321                                         return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true);
322
323                                 return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
324
325                         case MemberKind.InternalCompilerType:
326                                 //
327                                 // from the null literal to any reference-type.
328                                 //
329                                 if (expr_type == InternalType.NullLiteral) {
330                                         // Exlude internal compiler types
331                                         if (target_type.Kind == MemberKind.InternalCompilerType)
332                                                 return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
333
334                                         return TypeSpec.IsReferenceType (target_type);
335                                 }
336
337                                 //
338                                 // Implicit dynamic conversion
339                                 //
340                                 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
341                                         switch (target_type.Kind) {
342                                         case MemberKind.ArrayType:
343                                         case MemberKind.Class:
344                                         case MemberKind.Delegate:
345                                         case MemberKind.Interface:
346                                         case MemberKind.TypeParameter:
347                                                 return true;
348                                         }
349
350                                         // dynamic to __arglist
351                                         if (target_type == InternalType.Arglist)
352                                                 return true;
353
354                                         return false;
355                                 }
356
357                                 break;
358                         }
359
360                         return false;
361                 }
362
363                 public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
364                 {
365                         switch (target_type.BuiltinType) {
366                         //
367                         // From any non-nullable-value-type to the type object and dynamic
368                         //
369                         case BuiltinTypeSpec.Type.Object:
370                         case BuiltinTypeSpec.Type.Dynamic:
371                         //
372                         // From any non-nullable-value-type to the type System.ValueType
373                         //
374                         case BuiltinTypeSpec.Type.ValueType:
375                                 //
376                                 // No ned to check for nullable type as underlying type is always convertible
377                                 //
378                                 if (!TypeSpec.IsValueType (expr_type))
379                                         return null;
380
381                                 return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
382
383                         case BuiltinTypeSpec.Type.Enum:
384                                 //
385                                 // From any enum-type to the type System.Enum.
386                                 //
387                                 if (expr_type.IsEnum)
388                                         return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
389
390                                 break;
391                         }
392
393                         //
394                         // From a nullable-type to a reference type, if a boxing conversion exists from
395                         // the underlying type to the reference type
396                         //
397                         if (expr_type.IsNullableType) {
398                                 if (!TypeSpec.IsReferenceType (target_type))
399                                         return null;
400
401                                 var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
402
403                                 // "cast" underlying type to target type to emit correct InvalidCastException when
404                                 // underlying hierarchy changes without recompilation
405                                 if (res != null && expr != null)
406                                         res = new UnboxCast (res, target_type);
407
408                                 return res;
409                         }
410
411                         //
412                         // A value type has a boxing conversion to an interface type I if it has a boxing conversion
413                         // to an interface or delegate type I0 and I0 is variance-convertible to I
414                         //
415                         if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) {
416                                 return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
417                         }
418
419                         return null;
420                 }
421
422                 public static Expression ImplicitNulableConversion (ResolveContext ec, Expression expr, TypeSpec target_type)
423                 {
424                         TypeSpec expr_type = expr.Type;
425
426                         //
427                         // From null to any nullable type
428                         //
429                         if (expr_type == InternalType.NullLiteral)
430                                 return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location);
431
432                         // S -> T?
433                         TypeSpec t_el = Nullable.NullableInfo.GetUnderlyingType (target_type);
434
435                         // S? -> T?
436                         if (expr_type.IsNullableType)
437                                 expr_type = Nullable.NullableInfo.GetUnderlyingType (expr_type);
438
439                         //
440                         // Predefined implicit identity or implicit numeric conversion
441                         // has to exist between underlying type S and underlying type T
442                         //
443
444                         // conversion exists only mode
445                         if (ec == null) {
446                                 if (TypeSpecComparer.IsEqual (expr_type, t_el))
447                                         return EmptyExpression.Null;
448
449                                 if (expr is Constant)
450                                         return ((Constant) expr).ConvertImplicitly (t_el);
451
452                                 return ImplicitNumericConversion (null, expr_type, t_el);
453                         }
454
455                         Expression unwrap;
456                         if (expr_type != expr.Type)
457                                 unwrap = Nullable.Unwrap.Create (expr);
458                         else
459                                 unwrap = expr;
460
461                         Expression conv = unwrap;
462                         if (!TypeSpecComparer.IsEqual (expr_type, t_el)) {
463                                 if (conv is Constant)
464                                         conv = ((Constant)conv).ConvertImplicitly (t_el);
465                                 else
466                                         conv = ImplicitNumericConversion (conv, expr_type, t_el);
467
468                                 if (conv == null)
469                                         return null;
470                         }
471                         
472                         if (expr_type != expr.Type)
473                                 return new Nullable.LiftedConversion (conv, unwrap, target_type).Resolve (ec);
474
475                         return Nullable.Wrap.Create (conv, target_type);
476                 }
477
478                 /// <summary>
479                 ///   Implicit Numeric Conversions.
480                 ///
481                 ///   expr is the expression to convert, returns a new expression of type
482                 ///   target_type or null if an implicit conversion is not possible.
483                 /// </summary>
484                 public static Expression ImplicitNumericConversion (Expression expr, TypeSpec target_type)
485                 {
486                         return ImplicitNumericConversion (expr, expr.Type, target_type);
487                 }
488
489                 public static bool ImplicitNumericConversionExists (TypeSpec expr_type, TypeSpec target_type)
490                 {
491                         return ImplicitNumericConversion (null, expr_type, target_type) != null;
492                 }
493
494                 static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
495                 {
496                         switch (expr_type.BuiltinType) {
497                         case BuiltinTypeSpec.Type.SByte:
498                                 //
499                                 // From sbyte to short, int, long, float, double, decimal
500                                 //
501                                 switch (target_type.BuiltinType) {
502                                 case BuiltinTypeSpec.Type.Int:
503                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
504                                 case BuiltinTypeSpec.Type.Long:
505                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
506                                 case BuiltinTypeSpec.Type.Double:
507                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
508                                 case BuiltinTypeSpec.Type.Float:
509                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
510                                 case BuiltinTypeSpec.Type.Short:
511                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
512                                 case BuiltinTypeSpec.Type.Decimal:
513                                         return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
514
515                                 }
516
517                                 break;
518                         case BuiltinTypeSpec.Type.Byte:
519                                 //
520                                 // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
521                                 //
522                                 switch (target_type.BuiltinType) {
523                                 case BuiltinTypeSpec.Type.Int:
524                                 case BuiltinTypeSpec.Type.UInt:
525                                 case BuiltinTypeSpec.Type.Short:
526                                 case BuiltinTypeSpec.Type.UShort:
527                                         return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
528                                 case BuiltinTypeSpec.Type.ULong:
529                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
530                                 case BuiltinTypeSpec.Type.Long:
531                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
532                                 case BuiltinTypeSpec.Type.Float:
533                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
534                                 case BuiltinTypeSpec.Type.Double:
535                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
536                                 case BuiltinTypeSpec.Type.Decimal:
537                                         return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
538                                 }
539                                 break;
540                         case BuiltinTypeSpec.Type.Short:
541                                 //
542                                 // From short to int, long, float, double, decimal
543                                 //
544                                 switch (target_type.BuiltinType) {
545                                 case BuiltinTypeSpec.Type.Int:
546                                         return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
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);
555                                 }
556                                 break;
557                         case BuiltinTypeSpec.Type.UShort:
558                                 //
559                                 // From ushort to int, uint, long, ulong, float, double, decimal
560                                 //
561                                 switch (target_type.BuiltinType) {
562                                 case BuiltinTypeSpec.Type.Int:
563                                 case BuiltinTypeSpec.Type.UInt:
564                                         return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
565                                 case BuiltinTypeSpec.Type.ULong:
566                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
567                                 case BuiltinTypeSpec.Type.Long:
568                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
569                                 case BuiltinTypeSpec.Type.Double:
570                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
571                                 case BuiltinTypeSpec.Type.Float:
572                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
573                                 case BuiltinTypeSpec.Type.Decimal:
574                                         return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
575                                 }
576                                 break;
577                         case BuiltinTypeSpec.Type.Int:
578                                 //
579                                 // From int to long, float, double, decimal
580                                 //
581                                 switch (target_type.BuiltinType) {
582                                 case BuiltinTypeSpec.Type.Long:
583                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
584                                 case BuiltinTypeSpec.Type.Double:
585                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
586                                 case BuiltinTypeSpec.Type.Float:
587                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
588                                 case BuiltinTypeSpec.Type.Decimal:
589                                         return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
590                                 }
591                                 break;
592                         case BuiltinTypeSpec.Type.UInt:
593                                 //
594                                 // From uint to long, ulong, float, double, decimal
595                                 //
596                                 switch (target_type.BuiltinType) {
597                                 case BuiltinTypeSpec.Type.Long:
598                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
599                                 case BuiltinTypeSpec.Type.ULong:
600                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
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);
607                                 }
608                                 break;
609                         case BuiltinTypeSpec.Type.Long:
610                                 //
611                                 // From long to float, double, decimal
612                                 //
613                                 switch (target_type.BuiltinType) {
614                                 case BuiltinTypeSpec.Type.Double:
615                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
616                                 case BuiltinTypeSpec.Type.Float:
617                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
618                                 case BuiltinTypeSpec.Type.Decimal:
619                                         return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
620                                 }
621                                 break;
622                         case BuiltinTypeSpec.Type.ULong:
623                                 //
624                                 // From ulong to float, double, decimal
625                                 //
626                                 switch (target_type.BuiltinType) {
627                                 case BuiltinTypeSpec.Type.Double:
628                                         return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
629                                 case BuiltinTypeSpec.Type.Float:
630                                         return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
631                                 case BuiltinTypeSpec.Type.Decimal:
632                                         return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
633                                 }
634                                 break;
635                         case BuiltinTypeSpec.Type.Char:
636                                 //
637                                 // From char to ushort, int, uint, long, ulong, float, double, decimal
638                                 //
639                                 switch (target_type.BuiltinType) {
640                                 case BuiltinTypeSpec.Type.UShort:
641                                 case BuiltinTypeSpec.Type.Int:
642                                 case BuiltinTypeSpec.Type.UInt:
643                                         return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
644                                 case BuiltinTypeSpec.Type.ULong:
645                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
646                                 case BuiltinTypeSpec.Type.Long:
647                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
648                                 case BuiltinTypeSpec.Type.Float:
649                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
650                                 case BuiltinTypeSpec.Type.Double:
651                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
652                                 case BuiltinTypeSpec.Type.Decimal:
653                                         return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
654                                 }
655                                 break;
656                         case BuiltinTypeSpec.Type.Float:
657                                 //
658                                 // float to double
659                                 //
660                                 if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
661                                         return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
662                                 break;
663                         }
664
665                         return null;
666                 }
667
668                 //
669                 // Full version of implicit conversion
670                 //
671                 public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type)
672                 {
673                         if (ImplicitStandardConversionExists (expr, target_type))
674                                 return true;
675
676                         if (expr.Type == InternalType.AnonymousMethod) {
677                                 if (!target_type.IsDelegate && !target_type.IsExpressionTreeType)
678                                         return false;
679
680                                 AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
681                                 return ame.ImplicitStandardConversionExists (ec, target_type);
682                         }
683                         
684                         if (expr.eclass == ExprClass.MethodGroup) {
685                                 if (target_type.IsDelegate && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) {
686                                         MethodGroupExpr mg = expr as MethodGroupExpr;
687                                         if (mg != null)
688                                                 return DelegateCreation.ImplicitStandardConversionExists (ec, mg, target_type);
689                                 }
690
691                                 return false;
692                         }
693
694                         // Conversion from __arglist to System.ArgIterator
695                         if (expr.Type == InternalType.Arglist)
696                                 return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec;
697
698                         return UserDefinedConversion (ec, expr, target_type, true, true, Location.Null) != null;
699                 }
700
701                 //
702                 // Implicit standard conversion (only core conversions are used here)
703                 //
704                 public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type)
705                 {
706                         //
707                         // Identity conversions
708                         // Implicit numeric conversions
709                         // Implicit nullable conversions
710                         // Implicit reference conversions
711                         // Boxing conversions
712                         // Implicit constant expression conversions
713                         // Implicit conversions involving type parameters
714                         //
715
716                         TypeSpec expr_type = expr.Type;
717
718                         if (expr_type == target_type)
719                                 return true;
720
721                         if (target_type.IsNullableType)
722                                 return ImplicitNulableConversion (null, expr, target_type) != null;
723
724                         if (ImplicitNumericConversion (null, expr_type, target_type) != null)
725                                 return true;
726
727                         if (ImplicitReferenceConversionExists (expr_type, target_type, false))
728                                 return true;
729
730                         if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
731                                 return true;
732                         
733                         //
734                         // Implicit Constant Expression Conversions
735                         //
736                         if (expr is IntConstant){
737                                 int value = ((IntConstant) expr).Value;
738                                 switch (target_type.BuiltinType) {
739                                 case BuiltinTypeSpec.Type.SByte:
740                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
741                                                 return true;
742                                         break;
743                                 case BuiltinTypeSpec.Type.Byte:
744                                         if (value >= 0 && value <= Byte.MaxValue)
745                                                 return true;
746                                         break;
747                                 case BuiltinTypeSpec.Type.Short:
748                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
749                                                 return true;
750                                         break;
751                                 case BuiltinTypeSpec.Type.UShort:
752                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
753                                                 return true;
754                                         break;
755                                 case BuiltinTypeSpec.Type.UInt:
756                                         if (value >= 0)
757                                                 return true;
758                                         break;
759                                 case BuiltinTypeSpec.Type.ULong:
760                                          //
761                                          // we can optimize this case: a positive int32
762                                          // always fits on a uint64.  But we need an opcode
763                                          // to do it.
764                                          //
765                                         if (value >= 0)
766                                                 return true;
767
768                                         break;
769                                 }
770                         }
771
772                         if (expr is LongConstant && target_type.BuiltinType == BuiltinTypeSpec.Type.ULong){
773                                 //
774                                 // Try the implicit constant expression conversion
775                                 // from long to ulong, instead of a nice routine,
776                                 // we just inline it
777                                 //
778                                 long v = ((LongConstant) expr).Value;
779                                 if (v >= 0)
780                                         return true;
781                         }
782
783                         if (expr is IntegralConstant && target_type.IsEnum) {
784                                 var i = (IntegralConstant) expr;
785                                 //
786                                 // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
787                                 //
788                                 // An implicit enumeration conversion permits the decimal-integer-literal 0
789                                 // to be converted to any enum-type and to any nullable-type whose underlying
790                                 // type is an enum-type
791                                 //
792                                 return i.IsZeroInteger;
793                         }
794
795                         //
796                         // Implicit dynamic conversion for remaining value types. It should probably
797                         // go somewhere else
798                         //
799                         if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
800                                 switch (target_type.Kind) {
801                                 case MemberKind.Struct:
802                                 case MemberKind.Enum:
803                                         return true;
804                                 }
805
806                                 return false;
807                         }
808
809                         //
810                         // In an unsafe context implicit conversions is extended to include
811                         //
812                         // From any pointer-type to the type void*
813                         // From the null literal to any pointer-type.
814                         //
815                         // LAMESPEC: The specification claims this conversion is allowed in implicit conversion but
816                         // in reality implicit standard conversion uses it
817                         //
818                         if (target_type.IsPointer && expr.Type.IsPointer && ((PointerContainer) target_type).Element.Kind == MemberKind.Void)
819                                 return true;
820
821                         //
822                         // Struct identity conversion, including dynamic erasure
823                         //
824                         if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
825                                 return true;
826
827                         return false;
828                 }
829
830                 /// <summary>
831                 ///  Finds "most encompassed type" according to the spec (13.4.2)
832                 ///  amongst the methods in the MethodGroupExpr
833                 /// </summary>
834                 public static TypeSpec FindMostEncompassedType (IList<TypeSpec> types)
835                 {
836                         TypeSpec best = null;
837                         EmptyExpression expr;
838
839                         foreach (TypeSpec t in types) {
840                                 if (best == null) {
841                                         best = t;
842                                         continue;
843                                 }
844
845                                 expr = new EmptyExpression (t);
846                                 if (ImplicitStandardConversionExists (expr, best))
847                                         best = t;
848                         }
849
850                         expr = new EmptyExpression (best);
851                         foreach (TypeSpec t in types) {
852                                 if (best == t)
853                                         continue;
854                                 if (!ImplicitStandardConversionExists (expr, t)) {
855                                         best = null;
856                                         break;
857                                 }
858                         }
859
860                         return best;
861                 }
862
863                 //
864                 // Finds the most encompassing type (type into which all other
865                 // types can convert to) amongst the types in the given set
866                 //
867                 static TypeSpec FindMostEncompassingType (IList<TypeSpec> types)
868                 {
869                         if (types.Count == 0)
870                                 return null;
871
872                         if (types.Count == 1)
873                                 return types [0];
874
875                         TypeSpec best = null;
876                         for (int i = 0; i < types.Count; ++i) {
877                                 int ii = 0;
878                                 for (; ii < types.Count; ++ii) {
879                                         if (ii == i)
880                                                 continue;
881
882                                         var expr = new EmptyExpression (types[ii]);
883                                         if (!ImplicitStandardConversionExists (expr, types [i])) {
884                                                 ii = 0;
885                                                 break;
886                                         }
887                                 }
888
889                                 if (ii == 0)
890                                         continue;
891
892                                 if (best == null) {
893                                         best = types[i];
894                                         continue;
895                                 }
896
897                                 // Indicates multiple best types
898                                 return InternalType.FakeInternalType;
899                         }
900
901                         return best;
902                 }
903
904                 //
905                 // Finds the most specific source Sx according to the rules of the spec (13.4.4)
906                 // by making use of FindMostEncomp* methods. Applies the correct rules separately
907                 // for explicit and implicit conversion operators.
908                 //
909                 static TypeSpec FindMostSpecificSource (List<MethodSpec> list, TypeSpec sourceType, Expression source, bool apply_explicit_conv_rules)
910                 {
911                         TypeSpec[] src_types_set = null;
912
913                         //
914                         // Try exact match first, if any operator converts from S then Sx = S
915                         //
916                         for (int i = 0; i < list.Count; ++i) {
917                                 TypeSpec param_type = list [i].Parameters.Types [0];
918
919                                 if (param_type == sourceType)
920                                         return param_type;
921
922                                 if (src_types_set == null)
923                                         src_types_set = new TypeSpec [list.Count];
924
925                                 src_types_set [i] = param_type;
926                         }
927
928                         //
929                         // Explicit Conv rules
930                         //
931                         if (apply_explicit_conv_rules) {
932                                 var candidate_set = new List<TypeSpec> ();
933
934                                 foreach (TypeSpec param_type in src_types_set){
935                                         if (ImplicitStandardConversionExists (source, param_type))
936                                                 candidate_set.Add (param_type);
937                                 }
938
939                                 if (candidate_set.Count != 0)
940                                         return FindMostEncompassedType (candidate_set);
941                         }
942
943                         //
944                         // Final case
945                         //
946                         if (apply_explicit_conv_rules)
947                                 return FindMostEncompassingType (src_types_set);
948                         else
949                                 return FindMostEncompassedType (src_types_set);
950                 }
951
952                 /// <summary>
953                 ///  Finds the most specific target Tx according to section 13.4.4
954                 /// </summary>
955                 static public TypeSpec FindMostSpecificTarget (IList<MethodSpec> list,
956                                                            TypeSpec target, bool apply_explicit_conv_rules)
957                 {
958                         List<TypeSpec> tgt_types_set = null;
959
960                         //
961                         // If any operator converts to T then Tx = T
962                         //
963                         foreach (var mi in list){
964                                 TypeSpec ret_type = mi.ReturnType;
965                                 if (ret_type == target)
966                                         return ret_type;
967
968                                 if (tgt_types_set == null) {
969                                         tgt_types_set = new List<TypeSpec> (list.Count);
970                                 } else if (tgt_types_set.Contains (ret_type)) {
971                                         continue;
972                                 }
973
974                                 tgt_types_set.Add (ret_type);
975                         }
976
977                         //
978                         // Explicit conv rules
979                         //
980                         if (apply_explicit_conv_rules) {
981                                 var candidate_set = new List<TypeSpec> ();
982
983                                 foreach (TypeSpec ret_type in tgt_types_set) {
984                                         var expr = new EmptyExpression (ret_type);
985
986                                         if (ImplicitStandardConversionExists (expr, target))
987                                                 candidate_set.Add (ret_type);
988                                 }
989
990                                 if (candidate_set.Count != 0)
991                                         return FindMostEncompassingType (candidate_set);
992                         }
993
994                         //
995                         // Okay, final case !
996                         //
997                         if (apply_explicit_conv_rules)
998                                 return FindMostEncompassedType (tgt_types_set);
999                         else
1000                                 return FindMostEncompassingType (tgt_types_set);
1001                 }
1002
1003                 /// <summary>
1004                 ///  User-defined Implicit conversions
1005                 /// </summary>
1006                 static public Expression ImplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
1007                 {
1008                         return UserDefinedConversion (ec, source, target, true, false, loc);
1009                 }
1010
1011                 /// <summary>
1012                 ///  User-defined Explicit conversions
1013                 /// </summary>
1014                 static Expression ExplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
1015                 {
1016                         return UserDefinedConversion (ec, source, target, false, false, loc);
1017                 }
1018
1019                 static void FindApplicableUserDefinedConversionOperators (IList<MemberSpec> operators, Expression source, TypeSpec target, bool implicitOnly, ref List<MethodSpec> candidates)
1020                 {
1021                         if (source.Type.IsInterface) {
1022                                 // Neither A nor B are interface-types
1023                                 return;
1024                         }
1025
1026                         // For a conversion operator to be applicable, it must be possible
1027                         // to perform a standard conversion from the source type to
1028                         // the operand type of the operator, and it must be possible
1029                         // to perform a standard conversion from the result type of
1030                         // the operator to the target type.
1031
1032                         Expression texpr = null;
1033
1034                         foreach (MethodSpec op in operators) {
1035                                 
1036                                 // Can be null because MemberCache.GetUserOperator does not resize the array
1037                                 if (op == null)
1038                                         continue;
1039
1040                                 var t = op.Parameters.Types[0];
1041                                 if (source.Type != t && !ImplicitStandardConversionExists (source, t)) {
1042                                         if (implicitOnly)
1043                                                 continue;
1044
1045                                         if (!ImplicitStandardConversionExists (new EmptyExpression (t), source.Type))
1046                                                 continue;
1047                                 }
1048
1049                                 t = op.ReturnType;
1050
1051                                 if (t.IsInterface)
1052                                         continue;
1053
1054                                 if (target != t) {
1055                                         if (t.IsNullableType)
1056                                                 t = Nullable.NullableInfo.GetUnderlyingType (t);
1057
1058                                         if (!ImplicitStandardConversionExists (new EmptyExpression (t), target)) {
1059                                                 if (implicitOnly)
1060                                                         continue;
1061
1062                                                 if (texpr == null)
1063                                                         texpr = new EmptyExpression (target);
1064
1065                                                 if (!ImplicitStandardConversionExists (texpr, t))
1066                                                         continue;
1067                                         }
1068                                 }
1069
1070                                 if (candidates == null)
1071                                         candidates = new List<MethodSpec> ();
1072
1073                                 candidates.Add (op);
1074                         }
1075                 }
1076
1077                 //
1078                 // User-defined conversions
1079                 //
1080                 static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, bool probingOnly, Location loc)
1081                 {
1082                         List<MethodSpec> candidates = null;
1083
1084                         //
1085                         // If S or T are nullable types, source_type and target_type are their underlying types
1086                         // otherwise source_type and target_type are equal to S and T respectively.
1087                         //
1088                         TypeSpec source_type = source.Type;
1089                         TypeSpec target_type = target;
1090                         Expression source_type_expr;
1091                         bool nullable_source = false;
1092
1093                         if (source_type.IsNullableType) {
1094                                 // No unwrapping conversion S? -> T for non-reference types
1095                                 if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) {
1096                                         source_type_expr = source;
1097                                 } else {
1098                                         source_type_expr = Nullable.Unwrap.CreateUnwrapped (source);
1099                                         source_type = source_type_expr.Type;
1100                                         nullable_source = true;
1101                                 }
1102                         } else {
1103                                 source_type_expr = source;
1104                         }
1105
1106                         if (target_type.IsNullableType)
1107                                 target_type = Nullable.NullableInfo.GetUnderlyingType (target_type);
1108
1109                         // Only these containers can contain a user defined implicit or explicit operators
1110                         const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter;
1111
1112                         if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1113                                 bool declared_only = source_type.IsStruct;
1114
1115                                 var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only);
1116                                 if (operators != null) {
1117                                         FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1118                                 }
1119
1120                                 if (!implicitOnly) {
1121                                         operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only);
1122                                         if (operators != null) {
1123                                                 FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1124                                         }
1125                                 }
1126                         }
1127
1128                         if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1129                                 bool declared_only = target.IsStruct || implicitOnly;
1130
1131                                 var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only);
1132                                 if (operators != null) {
1133                                         FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1134                                 }
1135
1136                                 if (!implicitOnly) {
1137                                         operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only);
1138                                         if (operators != null) {
1139                                                 FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1140                                         }
1141                                 }
1142                         }
1143
1144                         if (candidates == null)
1145                                 return null;
1146
1147                         //
1148                         // Find the most specific conversion operator
1149                         //
1150                         MethodSpec most_specific_operator;
1151                         TypeSpec s_x, t_x;
1152                         if (candidates.Count == 1) {
1153                                 most_specific_operator = candidates[0];
1154                                 s_x = most_specific_operator.Parameters.Types[0];
1155                                 t_x = most_specific_operator.ReturnType;
1156                         } else {
1157                                 //
1158                                 // Pass original source type to find the best match against input type and
1159                                 // not the unwrapped expression
1160                                 //
1161                                 s_x = FindMostSpecificSource (candidates, source.Type, source_type_expr, !implicitOnly);
1162                                 if (s_x == null)
1163                                         return null;
1164
1165                                 t_x = FindMostSpecificTarget (candidates, target, !implicitOnly);
1166                                 if (t_x == null)
1167                                         return null;
1168
1169                                 most_specific_operator = null;
1170                                 for (int i = 0; i < candidates.Count; ++i) {
1171                                         if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) {
1172                                                 most_specific_operator = candidates[i];
1173                                                 break;
1174                                         }
1175                                 }
1176
1177                                 if (most_specific_operator == null) {
1178                                         //
1179                                         // Unless running in probing more
1180                                         //
1181                                         if (!probingOnly) {
1182                                                 MethodSpec ambig_arg = null;
1183                                                 foreach (var candidate in candidates) {
1184                                                         if (candidate.ReturnType == t_x)
1185                                                                 most_specific_operator = candidate;
1186                                                         else if (candidate.Parameters.Types[0] == s_x)
1187                                                                 ambig_arg = candidate;
1188                                                 }
1189
1190                                                 ec.Report.Error (457, loc,
1191                                                         "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'",
1192                                                         ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (),
1193                                                         source.Type.GetSignatureForError (), target.GetSignatureForError ());
1194                                         }
1195
1196                                         return ErrorExpression.Instance;
1197                                 }
1198                         }
1199
1200                         //
1201                         // Convert input type when it's different to best operator argument
1202                         //
1203                         if (s_x != source_type) {
1204                                 var c = source as Constant;
1205                                 if (c != null) {
1206                                         source = c.Reduce (ec, s_x);
1207                                         if (source == null)
1208                                                 c = null;
1209                                 }
1210
1211                                 if (c == null) {
1212                                         source = implicitOnly ?
1213                                                 ImplicitConversionStandard (ec, source_type_expr, s_x, loc) :
1214                                                 ExplicitConversionStandard (ec, source_type_expr, s_x, loc);
1215                                 }
1216                         } else {
1217                                 source = source_type_expr;
1218                         }
1219
1220                         source = new UserCast (most_specific_operator, source, loc).Resolve (ec);
1221
1222                         //
1223                         // Convert result type when it's different to best operator return type
1224                         //
1225                         if (t_x != target_type) {
1226                                 //
1227                                 // User operator is of T?
1228                                 //
1229                                 if (t_x.IsNullableType && (target.IsNullableType || !implicitOnly)) {
1230                                         //
1231                                         // User operator return type does not match target type we need
1232                                         // yet another conversion. This should happen for promoted numeric
1233                                         // types only
1234                                         //
1235                                         if (t_x != target) {
1236                                                 var unwrap = Nullable.Unwrap.CreateUnwrapped (source);
1237
1238                                                 source = implicitOnly ?
1239                                                         ImplicitConversionStandard (ec, unwrap, target_type, loc) :
1240                                                         ExplicitConversionStandard (ec, unwrap, target_type, loc);
1241
1242                                                 if (source == null)
1243                                                         return null;
1244
1245                                                 if (target.IsNullableType)
1246                                                         source = new Nullable.LiftedConversion (source, unwrap, target).Resolve (ec);
1247                                         }
1248                                 } else {
1249                                         source = implicitOnly ?
1250                                                 ImplicitConversionStandard (ec, source, target_type, loc) :
1251                                                 ExplicitConversionStandard (ec, source, target_type, loc);
1252
1253                                         if (source == null)
1254                                                 return null;
1255                                 }
1256                         }
1257
1258
1259                         //
1260                         // Source expression is of nullable type and underlying conversion returns
1261                         // only non-nullable type we need to lift it manually
1262                         //
1263                         if (nullable_source && !s_x.IsNullableType)
1264                                 return new Nullable.LiftedConversion (source, source_type_expr, target).Resolve (ec);
1265
1266                         //
1267                         // Target is of nullable type but source type is not, wrap the result expression
1268                         //
1269                         if (target.IsNullableType && !t_x.IsNullableType)
1270                                 source = Nullable.Wrap.Create (source, target);
1271
1272                         return source;
1273                 }
1274
1275                 /// <summary>
1276                 ///   Converts implicitly the resolved expression `expr' into the
1277                 ///   `target_type'.  It returns a new expression that can be used
1278                 ///   in a context that expects a `target_type'.
1279                 /// </summary>
1280                 static public Expression ImplicitConversion (ResolveContext ec, Expression expr,
1281                                                              TypeSpec target_type, Location loc)
1282                 {
1283                         Expression e;
1284
1285                         if (target_type == null)
1286                                 throw new Exception ("Target type is null");
1287
1288                         e = ImplicitConversionStandard (ec, expr, target_type, loc);
1289                         if (e != null)
1290                                 return e;
1291
1292                         e = ImplicitUserConversion (ec, expr, target_type, loc);
1293                         if (e != null)
1294                                 return e;
1295
1296                         return null;
1297                 }
1298
1299
1300                 /// <summary>
1301                 ///   Attempts to apply the `Standard Implicit
1302                 ///   Conversion' rules to the expression `expr' into
1303                 ///   the `target_type'.  It returns a new expression
1304                 ///   that can be used in a context that expects a
1305                 ///   `target_type'.
1306                 ///
1307                 ///   This is different from `ImplicitConversion' in that the
1308                 ///   user defined implicit conversions are excluded.
1309                 /// </summary>
1310                 static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr,
1311                                                                      TypeSpec target_type, Location loc)
1312                 {
1313                         return ImplicitConversionStandard (ec, expr, target_type, loc, false);
1314                 }
1315
1316                 static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast)
1317                 {
1318                         if (expr.eclass == ExprClass.MethodGroup){
1319                                 if (!target_type.IsDelegate){
1320                                         return null;
1321                                 }
1322
1323                                 //
1324                                 // Only allow anonymous method conversions on post ISO_1
1325                                 //
1326                                 if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){
1327                                         MethodGroupExpr mg = expr as MethodGroupExpr;
1328                                         if (mg != null)
1329                                                 return new ImplicitDelegateCreation (target_type, mg, loc).Resolve (ec);
1330                                 }
1331                         }
1332
1333                         TypeSpec expr_type = expr.Type;
1334                         Expression e;
1335
1336                         if (expr_type == target_type) {
1337                                 if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod)
1338                                         return expr;
1339                                 return null;
1340                         }
1341
1342                         if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1343                                 switch (target_type.Kind) {
1344                                 case MemberKind.ArrayType:
1345                                 case MemberKind.Class:
1346                                         if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object)
1347                                                 return EmptyCast.Create (expr, target_type);
1348
1349                                         goto case MemberKind.Struct;
1350                                 case MemberKind.Struct:
1351                                 case MemberKind.Delegate:
1352                                 case MemberKind.Enum:
1353                                 case MemberKind.Interface:
1354                                 case MemberKind.TypeParameter:
1355                                         Arguments args = new Arguments (1);
1356                                         args.Add (new Argument (expr));
1357                                         return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec);
1358                                 }
1359
1360                                 return null;
1361                         }
1362
1363                         if (target_type.IsNullableType)
1364                                 return ImplicitNulableConversion (ec, expr, target_type);
1365
1366                         //
1367                         // Attempt to do the implicit constant expression conversions
1368                         //
1369                         Constant c = expr as Constant;
1370                         if (c != null) {
1371                                 try {
1372                                         c = c.ConvertImplicitly (target_type);
1373                                 } catch {
1374                                         throw new InternalErrorException ("Conversion error", loc);
1375                                 }
1376                                 if (c != null)
1377                                         return c;
1378                         }
1379
1380                         e = ImplicitNumericConversion (expr, expr_type, target_type);
1381                         if (e != null)
1382                                 return e;
1383
1384                         e = ImplicitReferenceConversion (expr, target_type, explicit_cast);
1385                         if (e != null)
1386                                 return e;
1387
1388                         e = ImplicitBoxingConversion (expr, expr_type, target_type);
1389                         if (e != null)
1390                                 return e;
1391
1392                         if (expr is IntegralConstant && target_type.IsEnum){
1393                                 var i = (IntegralConstant) expr;
1394                                 //
1395                                 // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
1396                                 //
1397                                 // An implicit enumeration conversion permits the decimal-integer-literal 0
1398                                 // to be converted to any enum-type and to any nullable-type whose underlying
1399                                 // type is an enum-type
1400                                 //
1401                                 if (i.IsZeroInteger) {
1402                                         // Recreate 0 literal to remove any collected conversions
1403                                         return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type);
1404                                 }
1405                         }
1406
1407                         var target_pc = target_type as PointerContainer;
1408                         if (target_pc != null) {
1409                                 if (expr_type.IsPointer) {
1410                                         //
1411                                         // Pointer types are same when they have same element types
1412                                         //
1413                                         if (expr_type == target_pc)
1414                                                 return expr;
1415
1416                                         if (target_pc.Element.Kind == MemberKind.Void)
1417                                                 return EmptyCast.Create (expr, target_type);
1418
1419                                                 //return null;
1420                                 }
1421
1422                                 if (expr_type == InternalType.NullLiteral)
1423                                         return new NullPointer (target_type, loc);
1424                         }
1425
1426                         if (expr_type == InternalType.AnonymousMethod){
1427                                 AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
1428                                 Expression am = ame.Compatible (ec, target_type);
1429                                 if (am != null)
1430                                         return am.Resolve (ec);
1431
1432                                 // Avoid CS1503 after CS1661
1433                                 return ErrorExpression.Instance;
1434                         }
1435
1436                         if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec)
1437                                 return expr;
1438
1439                         //
1440                         // dynamic erasure conversion on value types
1441                         //
1442                         if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
1443                                 return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type);
1444
1445                         return null;
1446                 }
1447
1448                 /// <summary>
1449                 ///   Attempts to implicitly convert `source' into `target_type', using
1450                 ///   ImplicitConversion.  If there is no implicit conversion, then
1451                 ///   an error is signaled
1452                 /// </summary>
1453                 static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
1454                                                                      TypeSpec target_type, Location loc)
1455                 {
1456                         Expression e = ImplicitConversion (ec, source, target_type, loc);
1457                         if (e != null)
1458                                 return e;
1459
1460                         source.Error_ValueCannotBeConverted (ec, target_type, false);
1461
1462                         return null;
1463                 }
1464
1465                 /// <summary>
1466                 ///   Performs the explicit numeric conversions
1467                 ///
1468                 /// There are a few conversions that are not part of the C# standard,
1469                 /// they were interim hacks in the C# compiler that were supposed to
1470                 /// become explicit operators in the UIntPtr class and IntPtr class,
1471                 /// but for historical reasons it did not happen, so the C# compiler
1472                 /// ended up with these special hacks.
1473                 ///
1474                 /// See bug 59800 for details.
1475                 ///
1476                 /// The conversion are:
1477                 ///   UIntPtr->SByte
1478                 ///   UIntPtr->Int16
1479                 ///   UIntPtr->Int32
1480                 ///   IntPtr->UInt64
1481                 ///   UInt64->IntPtr
1482                 ///   SByte->UIntPtr
1483                 ///   Int16->UIntPtr
1484                 ///
1485                 /// </summary>
1486                 public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type)
1487                 {
1488                         // Not all predefined explicit numeric conversion are
1489                         // defined here, for some of them (mostly IntPtr/UIntPtr) we
1490                         // defer to user-operator handling which is now perfect but
1491                         // works for now
1492                         //
1493                         // LAMESPEC: Undocumented IntPtr/UIntPtr conversions
1494                         // IntPtr -> uint uses int
1495                         // UIntPtr -> long uses ulong
1496                         //
1497
1498                         switch (expr.Type.BuiltinType) {
1499                         case BuiltinTypeSpec.Type.SByte:
1500                                 //
1501                                 // From sbyte to byte, ushort, uint, ulong, char, uintptr
1502                                 //
1503                                 switch (target_type.BuiltinType) {
1504                                 case BuiltinTypeSpec.Type.Byte:
1505                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
1506                                 case BuiltinTypeSpec.Type.UShort:
1507                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
1508                                 case BuiltinTypeSpec.Type.UInt:
1509                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
1510                                 case BuiltinTypeSpec.Type.ULong:
1511                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
1512                                 case BuiltinTypeSpec.Type.Char:
1513                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
1514
1515                                 // One of the built-in conversions that belonged in the class library
1516                                 case BuiltinTypeSpec.Type.UIntPtr:
1517                                         return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true);
1518                                 }
1519                                 break;
1520                         case BuiltinTypeSpec.Type.Byte:
1521                                 //
1522                                 // From byte to sbyte and char
1523                                 //
1524                                 switch (target_type.BuiltinType) {
1525                                 case BuiltinTypeSpec.Type.SByte:
1526                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
1527                                 case BuiltinTypeSpec.Type.Char:
1528                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
1529                                 }
1530                                 break;
1531                         case BuiltinTypeSpec.Type.Short:
1532                                 //
1533                                 // From short to sbyte, byte, ushort, uint, ulong, char, uintptr
1534                                 //
1535                                 switch (target_type.BuiltinType) {
1536                                 case BuiltinTypeSpec.Type.SByte:
1537                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
1538                                 case BuiltinTypeSpec.Type.Byte:
1539                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
1540                                 case BuiltinTypeSpec.Type.UShort:
1541                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
1542                                 case BuiltinTypeSpec.Type.UInt:
1543                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
1544                                 case BuiltinTypeSpec.Type.ULong:
1545                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
1546                                 case BuiltinTypeSpec.Type.Char:
1547                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
1548
1549                                 // One of the built-in conversions that belonged in the class library
1550                                 case BuiltinTypeSpec.Type.UIntPtr:
1551                                         return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1552                                 }
1553                                 break;
1554                         case BuiltinTypeSpec.Type.UShort:
1555                                 //
1556                                 // From ushort to sbyte, byte, short, char
1557                                 //
1558                                 switch (target_type.BuiltinType) {
1559                                 case BuiltinTypeSpec.Type.SByte:
1560                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
1561                                 case BuiltinTypeSpec.Type.Byte:
1562                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
1563                                 case BuiltinTypeSpec.Type.Short:
1564                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
1565                                 case BuiltinTypeSpec.Type.Char:
1566                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
1567                                 }
1568                                 break;
1569                         case BuiltinTypeSpec.Type.Int:
1570                                 //
1571                                 // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
1572                                 //
1573                                 switch (target_type.BuiltinType) {
1574                                 case BuiltinTypeSpec.Type.SByte:
1575                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
1576                                 case BuiltinTypeSpec.Type.Byte:
1577                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
1578                                 case BuiltinTypeSpec.Type.Short:
1579                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
1580                                 case BuiltinTypeSpec.Type.UShort:
1581                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
1582                                 case BuiltinTypeSpec.Type.UInt:
1583                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
1584                                 case BuiltinTypeSpec.Type.ULong:
1585                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
1586                                 case BuiltinTypeSpec.Type.Char:
1587                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
1588
1589                                 // One of the built-in conversions that belonged in the class library
1590                                 case BuiltinTypeSpec.Type.UIntPtr:
1591                                         return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1592                                 }
1593                                 break;
1594                         case BuiltinTypeSpec.Type.UInt:
1595                                 //
1596                                 // From uint to sbyte, byte, short, ushort, int, char
1597                                 //
1598                                 switch (target_type.BuiltinType) {
1599                                 case BuiltinTypeSpec.Type.SByte:
1600                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
1601                                 case BuiltinTypeSpec.Type.Byte:
1602                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
1603                                 case BuiltinTypeSpec.Type.Short:
1604                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
1605                                 case BuiltinTypeSpec.Type.UShort:
1606                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
1607                                 case BuiltinTypeSpec.Type.Int:
1608                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
1609                                 case BuiltinTypeSpec.Type.Char:
1610                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
1611                                 }
1612                                 break;
1613                         case BuiltinTypeSpec.Type.Long:
1614                                 //
1615                                 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1616                                 //
1617                                 switch (target_type.BuiltinType) {
1618                                 case BuiltinTypeSpec.Type.SByte:
1619                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
1620                                 case BuiltinTypeSpec.Type.Byte:
1621                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
1622                                 case BuiltinTypeSpec.Type.Short:
1623                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
1624                                 case BuiltinTypeSpec.Type.UShort:
1625                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
1626                                 case BuiltinTypeSpec.Type.Int:
1627                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
1628                                 case BuiltinTypeSpec.Type.UInt:
1629                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
1630                                 case BuiltinTypeSpec.Type.ULong:
1631                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
1632                                 case BuiltinTypeSpec.Type.Char:
1633                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
1634                                 }
1635                                 break;
1636                         case BuiltinTypeSpec.Type.ULong:
1637                                 //
1638                                 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1639                                 //
1640                                 switch (target_type.BuiltinType) {
1641                                 case BuiltinTypeSpec.Type.SByte:
1642                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
1643                                 case BuiltinTypeSpec.Type.Byte:
1644                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
1645                                 case BuiltinTypeSpec.Type.Short:
1646                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
1647                                 case BuiltinTypeSpec.Type.UShort:
1648                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
1649                                 case BuiltinTypeSpec.Type.Int:
1650                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
1651                                 case BuiltinTypeSpec.Type.UInt:
1652                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
1653                                 case BuiltinTypeSpec.Type.Long:
1654                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
1655                                 case BuiltinTypeSpec.Type.Char:
1656                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
1657
1658                                 // One of the built-in conversions that belonged in the class library
1659                                 case BuiltinTypeSpec.Type.IntPtr:
1660                                         return new OperatorCast (EmptyCast.Create (expr, rc.BuiltinTypes.Long), target_type, true);
1661                                 }
1662                                 break;
1663                         case BuiltinTypeSpec.Type.Char:
1664                                 //
1665                                 // From char to sbyte, byte, short
1666                                 //
1667                                 switch (target_type.BuiltinType) {
1668                                 case BuiltinTypeSpec.Type.SByte:
1669                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
1670                                 case BuiltinTypeSpec.Type.Byte:
1671                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
1672                                 case BuiltinTypeSpec.Type.Short:
1673                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
1674                                 }
1675                                 break;
1676                         case BuiltinTypeSpec.Type.Float:
1677                                 //
1678                                 // From float to sbyte, byte, short,
1679                                 // ushort, int, uint, long, ulong, char
1680                                 // or decimal
1681                                 //
1682                                 switch (target_type.BuiltinType) {
1683                                 case BuiltinTypeSpec.Type.SByte:
1684                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
1685                                 case BuiltinTypeSpec.Type.Byte:
1686                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
1687                                 case BuiltinTypeSpec.Type.Short:
1688                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
1689                                 case BuiltinTypeSpec.Type.UShort:
1690                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
1691                                 case BuiltinTypeSpec.Type.Int:
1692                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
1693                                 case BuiltinTypeSpec.Type.UInt:
1694                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
1695                                 case BuiltinTypeSpec.Type.Long:
1696                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
1697                                 case BuiltinTypeSpec.Type.ULong:
1698                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
1699                                 case BuiltinTypeSpec.Type.Char:
1700                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
1701                                 case BuiltinTypeSpec.Type.Decimal:
1702                                         return new OperatorCast (expr, target_type, true);
1703                                 }
1704                                 break;
1705                         case BuiltinTypeSpec.Type.Double:
1706                                 //
1707                                 // From double to sbyte, byte, short,
1708                                 // ushort, int, uint, long, ulong,
1709                                 // char, float or decimal
1710                                 //
1711                                 switch (target_type.BuiltinType) {
1712                                 case BuiltinTypeSpec.Type.SByte:
1713                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
1714                                 case BuiltinTypeSpec.Type.Byte:
1715                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
1716                                 case BuiltinTypeSpec.Type.Short:
1717                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
1718                                 case BuiltinTypeSpec.Type.UShort:
1719                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
1720                                 case BuiltinTypeSpec.Type.Int:
1721                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
1722                                 case BuiltinTypeSpec.Type.UInt:
1723                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
1724                                 case BuiltinTypeSpec.Type.Long:
1725                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
1726                                 case BuiltinTypeSpec.Type.ULong:
1727                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
1728                                 case BuiltinTypeSpec.Type.Char:
1729                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
1730                                 case BuiltinTypeSpec.Type.Float:
1731                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
1732                                 case BuiltinTypeSpec.Type.Decimal:
1733                                         return new OperatorCast (expr, target_type, true);
1734                                 }
1735                                 break;
1736                         case BuiltinTypeSpec.Type.UIntPtr:
1737                                 //
1738                                 // Various built-in conversions that belonged in the class library
1739                                 //
1740                                 // from uintptr to sbyte, short, int32
1741                                 //
1742                                 switch (target_type.BuiltinType) {
1743                                 case BuiltinTypeSpec.Type.SByte:
1744                                         return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I1);
1745                                 case BuiltinTypeSpec.Type.Short:
1746                                         return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I2);
1747                                 case BuiltinTypeSpec.Type.Int:
1748                                         return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type);
1749                                 case BuiltinTypeSpec.Type.UInt:
1750                                         return new OperatorCast (expr, expr.Type, target_type, true);
1751                                 case BuiltinTypeSpec.Type.Long:
1752                                         return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.ULong, true), target_type);
1753                                 }
1754                                 break;
1755                         case BuiltinTypeSpec.Type.IntPtr:
1756                                 if (target_type.BuiltinType == BuiltinTypeSpec.Type.UInt)
1757                                         return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Int, true), target_type);
1758                                 if (target_type.BuiltinType == BuiltinTypeSpec.Type.ULong)
1759                                         return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Long, true), target_type);
1760                                 
1761                                 break;
1762                         case BuiltinTypeSpec.Type.Decimal:
1763                                 // From decimal to sbyte, byte, short,
1764                                 // ushort, int, uint, long, ulong, char,
1765                                 // float, or double
1766                                 switch (target_type.BuiltinType) {
1767                                 case BuiltinTypeSpec.Type.SByte:
1768                                 case BuiltinTypeSpec.Type.Byte:
1769                                 case BuiltinTypeSpec.Type.Short:
1770                                 case BuiltinTypeSpec.Type.UShort:
1771                                 case BuiltinTypeSpec.Type.Int:
1772                                 case BuiltinTypeSpec.Type.UInt:
1773                                 case BuiltinTypeSpec.Type.Long:
1774                                 case BuiltinTypeSpec.Type.ULong:
1775                                 case BuiltinTypeSpec.Type.Char:
1776                                 case BuiltinTypeSpec.Type.Float:
1777                                 case BuiltinTypeSpec.Type.Double:
1778                                         return new OperatorCast (expr, expr.Type, target_type, true);
1779                                 }
1780
1781                                 break;
1782                         }
1783
1784                         return null;
1785                 }
1786
1787                 /// <summary>
1788                 ///  Returns whether an explicit reference conversion can be performed
1789                 ///  from source_type to target_type
1790                 /// </summary>
1791                 public static bool ExplicitReferenceConversionExists (TypeSpec source_type, TypeSpec target_type)
1792                 {
1793                         Expression e = ExplicitReferenceConversion (null, source_type, target_type);
1794                         if (e == null)
1795                                 return false;
1796
1797                         if (e == EmptyExpression.Null)
1798                                 return true;
1799
1800                         throw new InternalErrorException ("Invalid probing conversion result");
1801                 }
1802
1803                 /// <summary>
1804                 ///   Implements Explicit Reference conversions
1805                 /// </summary>
1806                 static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
1807                 {
1808                         //
1809                         // From object to a generic parameter
1810                         //
1811                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type))
1812                                 return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1813
1814                         //
1815                         // Explicit type parameter conversion.
1816                         //
1817                         if (source_type.Kind == MemberKind.TypeParameter)
1818                                 return ExplicitTypeParameterConversion (source, source_type, target_type);
1819
1820                         bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum;
1821
1822                         //
1823                         // Unboxing conversion from System.ValueType to any non-nullable-value-type
1824                         //
1825                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type)
1826                                 return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1827
1828                         //
1829                         // From object or dynamic to any reference type or value type (unboxing)
1830                         //
1831                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1832                                 if (target_type.IsPointer)
1833                                         return null;
1834
1835                                 return
1836                                         source == null ? EmptyExpression.Null :
1837                                         target_is_value_type ? new UnboxCast (source, target_type) :
1838                                         source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) :
1839                                         new ClassCast (source, target_type);
1840                         }
1841
1842                         //
1843                         // From any class S to any class-type T, provided S is a base class of T
1844                         //
1845                         if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true))
1846                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1847
1848                         //
1849                         // From any interface-type S to to any class type T, provided T is not
1850                         // sealed, or provided T implements S.
1851                         //
1852                         if (source_type.Kind == MemberKind.Interface) {
1853                                 if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) {
1854                                         if (source == null)
1855                                                 return EmptyExpression.Null;
1856
1857                                         //
1858                                         // Unboxing conversion from any interface-type to any non-nullable-value-type that
1859                                         // implements the interface-type
1860                                         //
1861                                         return target_is_value_type ? new UnboxCast (source, target_type) : (Expression) new ClassCast (source, target_type);
1862                                 }
1863
1864                                 //
1865                                 // From System.Collections.Generic.IList<T> and its base interfaces to a one-dimensional
1866                                 // array type S[], provided there is an implicit or explicit reference conversion from S to T.
1867                                 //
1868                                 var target_array = target_type as ArrayContainer;
1869                                 if (target_array != null && IList_To_Array (source_type, target_array))
1870                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1871
1872                                 return null;
1873                         }
1874
1875                         var source_array = source_type as ArrayContainer;
1876                         if (source_array != null) {
1877                                 var target_array = target_type as ArrayContainer;
1878                                 if (target_array != null) {
1879                                         //
1880                                         // From System.Array to any array-type
1881                                         //
1882                                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array)
1883                                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1884
1885                                         //
1886                                         // From an array type S with an element type Se to an array type T with an
1887                                         // element type Te provided all the following are true:
1888                                         //     * S and T differe only in element type, in other words, S and T
1889                                         //       have the same number of dimensions.
1890                                         //     * Both Se and Te are reference types
1891                                         //     * An explicit reference conversions exist from Se to Te
1892                                         //
1893                                         if (source_array.Rank == target_array.Rank) {
1894
1895                                                 source_type = source_array.Element;
1896                                                 if (!TypeSpec.IsReferenceType (source_type))
1897                                                         return null;
1898
1899                                                 var target_element = target_array.Element;
1900                                                 if (!TypeSpec.IsReferenceType (target_element))
1901                                                         return null;
1902
1903                                                 if (ExplicitReferenceConversionExists (source_type, target_element))
1904                                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1905                                                         
1906                                                 return null;
1907                                         }
1908                                 }
1909
1910                                 //
1911                                 // From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, 
1912                                 // provided that there is an explicit reference conversion from S to T
1913                                 //
1914                                 if (ArrayToIList (source_array, target_type, true))
1915                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1916
1917                                 return null;
1918                         }
1919
1920                         //
1921                         // From any class type S to any interface T, provides S is not sealed
1922                         // and provided S does not implement T.
1923                         //
1924                         if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type, true)) {
1925                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1926                         }
1927
1928                         //
1929                         // From System delegate to any delegate-type
1930                         //
1931                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && target_type.IsDelegate)
1932                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1933
1934                         //
1935                         // From variant generic delegate to same variant generic delegate type
1936                         //
1937                         if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) {
1938                                 var tparams = source_type.MemberDefinition.TypeParameters;
1939                                 var targs_src = source_type.TypeArguments;
1940                                 var targs_dst = target_type.TypeArguments;
1941                                 int i;
1942                                 for (i = 0; i < tparams.Length; ++i) {
1943                                         //
1944                                         // If TP is invariant, types have to be identical
1945                                         //
1946                                         if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i]))
1947                                                 continue;
1948
1949                                         if (tparams[i].Variance == Variance.Covariant) {
1950                                                 //
1951                                                 //If TP is covariant, an implicit or explicit identity or reference conversion is required
1952                                                 //
1953                                                 if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1954                                                         continue;
1955
1956                                                 if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1957                                                         continue;
1958
1959                                         } else if (tparams[i].Variance == Variance.Contravariant) {
1960                                                 //
1961                                                 //If TP is contravariant, both are either identical or reference types
1962                                                 //
1963                                                 if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i]))
1964                                                         continue;
1965                                         }
1966
1967                                         break;
1968                                 }
1969
1970                                 if (i == tparams.Length)
1971                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1972                         }
1973
1974                         return null;
1975                 }
1976
1977                 /// <summary>
1978                 ///   Performs an explicit conversion of the expression `expr' whose
1979                 ///   type is expr.Type to `target_type'.
1980                 /// </summary>
1981                 static public Expression ExplicitConversionCore (ResolveContext ec, Expression expr,
1982                                                                  TypeSpec target_type, Location loc)
1983                 {
1984                         TypeSpec expr_type = expr.Type;
1985
1986                         // Explicit conversion includes implicit conversion and it used for enum underlying types too
1987                         Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true);
1988                         if (ne != null)
1989                                 return ne;
1990
1991                         if (expr_type.IsEnum) {
1992                                 TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1993                                 Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type));
1994                                 if (underlying.Type == real_target)
1995                                         ne = underlying;
1996
1997                                 if (ne == null)
1998                                         ne = ImplicitNumericConversion (underlying, real_target);
1999
2000                                 if (ne == null)
2001                                         ne = ExplicitNumericConversion (ec, underlying, real_target);
2002
2003                                 //
2004                                 // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
2005                                 //
2006                                 if (ne == null && (real_target.BuiltinType == BuiltinTypeSpec.Type.IntPtr || real_target.BuiltinType == BuiltinTypeSpec.Type.UIntPtr))
2007                                         ne = ExplicitUserConversion (ec, underlying, real_target, loc);
2008
2009                                 return ne != null ? EmptyCast.Create (ne, target_type) : null;
2010                         }
2011
2012                         if (target_type.IsEnum) {
2013                                 //
2014                                 // System.Enum can be unboxed to any enum-type
2015                                 //
2016                                 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Enum)
2017                                         return new UnboxCast (expr, target_type);
2018
2019                                 TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
2020
2021                                 if (expr_type == real_target)
2022                                         return EmptyCast.Create (expr, target_type);
2023
2024                                 Constant c = expr as Constant;
2025                                 if (c != null) {
2026                                         c = c.TryReduce (ec, real_target);
2027                                         if (c != null)
2028                                                 return c;
2029                                 } else {
2030                                         ne = ImplicitNumericConversion (expr, real_target);
2031                                         if (ne != null)
2032                                                 return EmptyCast.Create (ne, target_type);
2033
2034                                         ne = ExplicitNumericConversion (ec, expr, real_target);
2035                                         if (ne != null)
2036                                                 return EmptyCast.Create (ne, target_type);
2037
2038                                         //
2039                                         // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
2040                                         //
2041                                         if (expr_type.BuiltinType == BuiltinTypeSpec.Type.IntPtr || expr_type.BuiltinType == BuiltinTypeSpec.Type.UIntPtr) {
2042                                                 ne = ExplicitUserConversion (ec, expr, real_target, loc);
2043                                                 if (ne != null)
2044                                                         return ExplicitConversionCore (ec, ne, target_type, loc);
2045                                         }
2046                                 }
2047                         } else {
2048                                 ne = ExplicitNumericConversion (ec, expr, target_type);
2049                                 if (ne != null)
2050                                         return ne;
2051                         }
2052
2053                         //
2054                         // Skip the ExplicitReferenceConversion because we can not convert
2055                         // from Null to a ValueType, and ExplicitReference wont check against
2056                         // null literal explicitly
2057                         //
2058                         if (expr_type != InternalType.NullLiteral) {
2059                                 ne = ExplicitReferenceConversion (expr, expr_type, target_type);
2060                                 if (ne != null)
2061                                         return ne;
2062                         }
2063
2064                         if (ec.IsUnsafe){
2065                                 ne = ExplicitUnsafe (expr, target_type);
2066                                 if (ne != null)
2067                                         return ne;
2068                         }
2069                         
2070                         return null;
2071                 }
2072
2073                 public static Expression ExplicitUnsafe (Expression expr, TypeSpec target_type)
2074                 {
2075                         TypeSpec expr_type = expr.Type;
2076
2077                         if (target_type.IsPointer){
2078                                 if (expr_type.IsPointer)
2079                                         return EmptyCast.Create (expr, target_type);
2080
2081                                 switch (expr_type.BuiltinType) {
2082                                 case BuiltinTypeSpec.Type.SByte:
2083                                 case BuiltinTypeSpec.Type.Short:
2084                                 case BuiltinTypeSpec.Type.Int:
2085                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
2086
2087                                 case BuiltinTypeSpec.Type.UShort:
2088                                 case BuiltinTypeSpec.Type.UInt:
2089                                 case BuiltinTypeSpec.Type.Byte:
2090                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2091
2092                                 case BuiltinTypeSpec.Type.Long:
2093                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I);
2094
2095                                 case BuiltinTypeSpec.Type.ULong:
2096                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I);
2097                                 }
2098                         }
2099
2100                         if (expr_type.IsPointer){
2101                                 switch (target_type.BuiltinType) {
2102                                 case BuiltinTypeSpec.Type.SByte:
2103                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
2104                                 case BuiltinTypeSpec.Type.Byte:
2105                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
2106                                 case BuiltinTypeSpec.Type.Short:
2107                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
2108                                 case BuiltinTypeSpec.Type.UShort:
2109                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
2110                                 case BuiltinTypeSpec.Type.Int:
2111                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
2112                                 case BuiltinTypeSpec.Type.UInt:
2113                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
2114                                 case BuiltinTypeSpec.Type.Long:
2115                                         return new ConvCast (expr, target_type, ConvCast.Mode.I_I8);
2116                                 case BuiltinTypeSpec.Type.ULong:
2117                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
2118                                 }
2119                         }
2120                         return null;
2121                 }
2122
2123                 /// <summary>
2124                 ///   Same as ExplicitConversion, only it doesn't include user defined conversions
2125                 /// </summary>
2126                 static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr,
2127                                                                      TypeSpec target_type, Location l)
2128                 {
2129                         int errors = ec.Report.Errors;
2130                         Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
2131                         if (ec.Report.Errors > errors)
2132                                 return null;
2133
2134                         if (ne != null)
2135                                 return ne;
2136
2137                         ne = ExplicitNumericConversion (ec, expr, target_type);
2138                         if (ne != null)
2139                                 return ne;
2140
2141                         ne = ExplicitReferenceConversion (expr, expr.Type, target_type);
2142                         if (ne != null)
2143                                 return ne;
2144
2145                         if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void)
2146                                 return EmptyCast.Create (expr, target_type);
2147
2148                         expr.Error_ValueCannotBeConverted (ec, target_type, true);
2149                         return null;
2150                 }
2151
2152                 /// <summary>
2153                 ///   Performs an explicit conversion of the expression `expr' whose
2154                 ///   type is expr.Type to `target_type'.
2155                 /// </summary>
2156                 static public Expression ExplicitConversion (ResolveContext ec, Expression expr,
2157                         TypeSpec target_type, Location loc)
2158                 {
2159                         Expression e = ExplicitConversionCore (ec, expr, target_type, loc);
2160                         if (e != null) {
2161                                 //
2162                                 // Don't eliminate explicit precission casts
2163                                 //
2164                                 if (e == expr) {
2165                                         if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float)
2166                                                 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
2167                                         
2168                                         if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
2169                                                 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
2170                                 }
2171                                         
2172                                 return e;
2173                         }
2174
2175                         TypeSpec expr_type = expr.Type;
2176                         if (target_type.IsNullableType) {
2177                                 TypeSpec target;
2178
2179                                 if (expr_type.IsNullableType) {
2180                                         target = Nullable.NullableInfo.GetUnderlyingType (target_type);
2181                                         Expression unwrap = Nullable.Unwrap.Create (expr);
2182                                         e = ExplicitConversion (ec, unwrap, target, expr.Location);
2183                                         if (e == null)
2184                                                 return null;
2185
2186                                         return new Nullable.LiftedConversion (e, unwrap, target_type).Resolve (ec);
2187                                 }
2188                                 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2189                                         return new UnboxCast (expr, target_type);
2190                                 }
2191
2192                                 target = TypeManager.GetTypeArguments (target_type) [0];
2193                                 e = ExplicitConversionCore (ec, expr, target, loc);
2194                                 if (e != null)
2195                                         return TypeSpec.IsReferenceType (expr.Type) ? new UnboxCast (expr, target_type) : Nullable.Wrap.Create (e, target_type);
2196                         } else if (expr_type.IsNullableType) {
2197                                 e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
2198                                 if (e != null)
2199                                         return e;
2200
2201                                 e = Nullable.Unwrap.Create (expr, false);                       
2202                                 e = ExplicitConversionCore (ec, e, target_type, loc);
2203                                 if (e != null)
2204                                         return EmptyCast.Create (e, target_type);
2205                         }
2206                         
2207                         e = ExplicitUserConversion (ec, expr, target_type, loc);
2208                         if (e != null)
2209                                 return e;                       
2210
2211                         expr.Error_ValueCannotBeConverted (ec, target_type, true);
2212                         return null;
2213                 }
2214         }
2215 }