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