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