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