Defer null check to resolver
[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                         // Neither A nor B are interface-types
982                         if (source.Type.IsInterface)
983                                 return;
984
985                         // For a conversion operator to be applicable, it must be possible
986                         // to perform a standard conversion from the source type to
987                         // the operand type of the operator, and it must be possible
988                         // to perform a standard conversion from the result type of
989                         // the operator to the target type.
990
991                         Expression texpr = null;
992
993                         foreach (MethodSpec op in operators) {
994                                 
995                                 // Can be null because MemberCache.GetUserOperator does not resize the array
996                                 if (op == null)
997                                         continue;
998
999                                 var t = op.Parameters.Types[0];
1000                                 if (source.Type != t && !ImplicitStandardConversionExists (source, t)) {
1001                                         if (implicitOnly)
1002                                                 continue;
1003
1004                                         if (!ImplicitStandardConversionExists (new EmptyExpression (t), source.Type))
1005                                                 continue;
1006                                 }
1007
1008                                 t = op.ReturnType;
1009
1010                                 // LAMESPEC: Exclude UIntPtr -> int conversion
1011                                 if (t == TypeManager.uint32_type && source.Type == TypeManager.uintptr_type)
1012                                         continue;
1013
1014                                 if (t.IsInterface)
1015                                         continue;
1016
1017                                 if (target != t && !ImplicitStandardConversionExists (new EmptyExpression (t), target)) {
1018                                         if (implicitOnly)
1019                                                 continue;
1020
1021                                         if (texpr == null)
1022                                                 texpr = new EmptyExpression (target);
1023
1024                                         if (!ImplicitStandardConversionExists (texpr, t))
1025                                                 continue;
1026                                 }
1027
1028                                 if (candidates == null)
1029                                         candidates = new List<MethodSpec> ();
1030
1031                                 candidates.Add (op);
1032                         }
1033                 }
1034
1035                 //
1036                 // User-defined conversions
1037                 //
1038                 static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, Location loc)
1039                 {
1040                         List<MethodSpec> candidates = null;
1041
1042                         //
1043                         // If S or T are nullable types, S0 and T0 are their underlying types
1044                         // otherwise S0 and T0 are equal to S and T respectively.
1045                         //
1046                         TypeSpec source_type = source.Type;
1047                         TypeSpec target_type = target;
1048                         Expression unwrap;
1049
1050                         if (TypeManager.IsNullableType (source_type)) {
1051                                 // No implicit conversion S? -> T for non-reference types
1052                                 if (implicitOnly && !TypeManager.IsReferenceType (target_type) && !TypeManager.IsNullableType (target_type))
1053                                         return null;
1054
1055                                 unwrap = source = Nullable.Unwrap.Create (source);
1056                                 source_type = source.Type;
1057                         } else {
1058                                 unwrap = null;
1059                         }
1060
1061                         if (TypeManager.IsNullableType (target_type))
1062                                 target_type = Nullable.NullableInfo.GetUnderlyingType (target_type);
1063
1064                         // Only these containers can contain a user defined implicit or explicit operators
1065                         const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter;
1066
1067                         if ((source_type.Kind & user_conversion_kinds) != 0 && source_type != TypeManager.decimal_type) {
1068                                 bool declared_only = source_type.IsStruct;
1069
1070                                 var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only);
1071                                 if (operators != null) {
1072                                         FindApplicableUserDefinedConversionOperators (operators, source, target_type, implicitOnly, ref candidates);
1073                                 }
1074
1075                                 if (!implicitOnly) {
1076                                         operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only);
1077                                         if (operators != null) {
1078                                                 FindApplicableUserDefinedConversionOperators (operators, source, target_type, false, ref candidates);
1079                                         }
1080                                 }
1081                         }
1082
1083                         if ((target.Kind & user_conversion_kinds) != 0 && target != TypeManager.decimal_type) {
1084                                 bool declared_only = target.IsStruct || implicitOnly;
1085
1086                                 var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only);
1087                                 if (operators != null) {
1088                                         FindApplicableUserDefinedConversionOperators (operators, source, target_type, implicitOnly, ref candidates);
1089                                 }
1090
1091                                 if (!implicitOnly) {
1092                                         operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only);
1093                                         if (operators != null) {
1094                                                 FindApplicableUserDefinedConversionOperators (operators, source, target_type, false, ref candidates);
1095                                         }
1096                                 }
1097                         }
1098
1099                         if (candidates == null)
1100                                 return null;
1101
1102                         //
1103                         // Find the most specific conversion operator
1104                         //
1105                         MethodSpec most_specific_operator;
1106                         TypeSpec s_x, t_x;
1107                         if (candidates.Count == 1) {
1108                                 most_specific_operator = candidates[0];
1109                                 s_x = most_specific_operator.Parameters.Types[0];
1110                                 t_x = most_specific_operator.ReturnType;
1111                         } else {
1112                                 s_x = FindMostSpecificSource (candidates, source, !implicitOnly);
1113                                 if (s_x == null)
1114                                         return null;
1115
1116                                 t_x = FindMostSpecificTarget (candidates, target, !implicitOnly);
1117                                 if (t_x == null)
1118                                         return null;
1119
1120                                 most_specific_operator = candidates[0];
1121
1122                                 for (int i = 1; i < candidates.Count; ++i) {
1123                                         if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) {
1124                                                 most_specific_operator = candidates[i];
1125                                                 break;
1126                                         }
1127                                 }
1128                         }
1129
1130                         //
1131                         // Convert input type when it's different to best operator argument
1132                         //
1133                         if (s_x != source.Type)
1134                                 source = implicitOnly ?
1135                                         ImplicitConversionStandard (ec, source, s_x, loc) :
1136                                         ExplicitConversionStandard (ec, source, s_x, loc);
1137
1138                         source = new UserCast (most_specific_operator, source, loc).Resolve (ec);
1139
1140                         //
1141                         // Convert result type when it's different to best operator return type
1142                         //
1143                         if (t_x != target_type) {
1144                                 //
1145                                 // User operator is of T?, no need to lift it
1146                                 //
1147                                 if (TypeManager.IsNullableType (t_x) && t_x == target)
1148                                         return source;
1149
1150                                 source = implicitOnly ?
1151                                         ImplicitConversionStandard (ec, source, target_type, loc) :
1152                                         ExplicitConversionStandard (ec, source, target_type, loc);
1153                         }
1154
1155                         //
1156                         // Source expression is of nullable type, lift the result in case of it's null
1157                         //
1158                         if (unwrap != null && (TypeManager.IsReferenceType (target) || target_type != target))
1159                                 source = new Nullable.Lifted (source, unwrap, target).Resolve (ec);
1160                         else if (target_type != target)
1161                                 source = Nullable.Wrap.Create (source, target);
1162
1163                         return source;
1164                 }
1165
1166                 /// <summary>
1167                 ///   Converts implicitly the resolved expression `expr' into the
1168                 ///   `target_type'.  It returns a new expression that can be used
1169                 ///   in a context that expects a `target_type'.
1170                 /// </summary>
1171                 static public Expression ImplicitConversion (ResolveContext ec, Expression expr,
1172                                                              TypeSpec target_type, Location loc)
1173                 {
1174                         Expression e;
1175
1176                         if (target_type == null)
1177                                 throw new Exception ("Target type is null");
1178
1179                         e = ImplicitConversionStandard (ec, expr, target_type, loc);
1180                         if (e != null)
1181                                 return e;
1182
1183                         e = ImplicitUserConversion (ec, expr, target_type, loc);
1184                         if (e != null)
1185                                 return e;
1186
1187                         return null;
1188                 }
1189
1190
1191                 /// <summary>
1192                 ///   Attempts to apply the `Standard Implicit
1193                 ///   Conversion' rules to the expression `expr' into
1194                 ///   the `target_type'.  It returns a new expression
1195                 ///   that can be used in a context that expects a
1196                 ///   `target_type'.
1197                 ///
1198                 ///   This is different from `ImplicitConversion' in that the
1199                 ///   user defined implicit conversions are excluded.
1200                 /// </summary>
1201                 static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr,
1202                                                                      TypeSpec target_type, Location loc)
1203                 {
1204                         return ImplicitConversionStandard (ec, expr, target_type, loc, false);
1205                 }
1206
1207                 static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast)
1208                 {
1209                         if (expr.eclass == ExprClass.MethodGroup){
1210                                 if (!TypeManager.IsDelegateType (target_type)){
1211                                         return null;
1212                                 }
1213
1214                                 //
1215                                 // Only allow anonymous method conversions on post ISO_1
1216                                 //
1217                                 if (RootContext.Version != LanguageVersion.ISO_1){
1218                                         MethodGroupExpr mg = expr as MethodGroupExpr;
1219                                         if (mg != null)
1220                                                 return ImplicitDelegateCreation.Create (
1221                                                         ec, mg, target_type, loc);
1222                                 }
1223                         }
1224
1225                         TypeSpec expr_type = expr.Type;
1226                         Expression e;
1227
1228                         if (expr_type == target_type) {
1229                                 if (expr_type != InternalType.Null && expr_type != InternalType.AnonymousMethod)
1230                                         return expr;
1231                                 return null;
1232                         }
1233
1234                         if (expr_type == InternalType.Dynamic) {
1235                                 switch (target_type.Kind) {
1236                                 case MemberKind.ArrayType:
1237                                 case MemberKind.Class:
1238                                         if (target_type == TypeManager.object_type)
1239                                                 return EmptyCast.Create (expr, target_type);
1240
1241                                         goto case MemberKind.Struct;
1242                                 case MemberKind.Struct:
1243                                 case MemberKind.Delegate:
1244                                 case MemberKind.Enum:
1245                                 case MemberKind.Interface:
1246                                 case MemberKind.TypeParameter:
1247                                         Arguments args = new Arguments (1);
1248                                         args.Add (new Argument (expr));
1249                                         return new DynamicConversion (target_type, 0, args, loc).Resolve (ec);
1250                                 }
1251
1252                                 return null;
1253                         }
1254
1255                         if (TypeManager.IsNullableType (target_type))
1256                                 return ImplicitNulableConversion (ec, expr, target_type);
1257
1258                         //
1259                         // Attempt to do the implicit constant expression conversions
1260                         //
1261                         Constant c = expr as Constant;
1262                         if (c != null) {
1263                                 try {
1264                                         c = c.ConvertImplicitly (ec, target_type);
1265                                 } catch {
1266                                         Console.WriteLine ("Conversion error happened in line {0}", loc);
1267                                         throw;
1268                                 }
1269                                 if (c != null)
1270                                         return c;
1271                         }
1272
1273                         e = ImplicitNumericConversion (expr, expr_type, target_type);
1274                         if (e != null)
1275                                 return e;
1276
1277                         e = ImplicitReferenceConversion (expr, target_type, explicit_cast);
1278                         if (e != null)
1279                                 return e;
1280
1281                         if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)){
1282                                 var i = (IntegralConstant) expr;
1283                                 //
1284                                 // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
1285                                 //
1286                                 // An implicit enumeration conversion permits the decimal-integer-literal 0
1287                                 // to be converted to any enum-type and to any nullable-type whose underlying
1288                                 // type is an enum-type
1289                                 //
1290                                 if (i.IsZeroInteger) {
1291                                         // Recreate 0 literal to remove any collected conversions
1292                                         return new EnumConstant (new IntLiteral (0, i.Location), target_type).Resolve (ec);
1293                                 }
1294                         }
1295
1296                         if (ec.IsUnsafe) {
1297                                 if (expr_type.IsPointer){
1298                                         if (target_type == TypeManager.void_ptr_type)
1299                                                 return EmptyCast.Create (expr, target_type);
1300
1301                                         //
1302                                         // yep, comparing pointer types cant be done with
1303                                         // t1 == t2, we have to compare their element types.
1304                                         //
1305                                         if (target_type.IsPointer){
1306                                                 if (TypeManager.GetElementType(target_type) == TypeManager.GetElementType(expr_type))
1307                                                         return expr;
1308
1309                                                 //return null;
1310                                         }
1311                                 }
1312
1313                                 if (expr_type == InternalType.Null && target_type.IsPointer)
1314                                         return EmptyCast.Create (new NullPointer (loc), target_type);
1315                         }
1316
1317                         if (expr_type == InternalType.AnonymousMethod){
1318                                 AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
1319                                 Expression am = ame.Compatible (ec, target_type);
1320                                 if (am != null)
1321                                         return am.Resolve (ec);
1322                         }
1323
1324                         if (expr_type == InternalType.Arglist && target_type == TypeManager.arg_iterator_type)
1325                                 return expr;
1326
1327                         return null;
1328                 }
1329
1330                 /// <summary>
1331                 ///   Attempts to implicitly convert `source' into `target_type', using
1332                 ///   ImplicitConversion.  If there is no implicit conversion, then
1333                 ///   an error is signaled
1334                 /// </summary>
1335                 static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
1336                                                                      TypeSpec target_type, Location loc)
1337                 {
1338                         Expression e = ImplicitConversion (ec, source, target_type, loc);
1339                         if (e != null)
1340                                 return e;
1341
1342                         source.Error_ValueCannotBeConverted (ec, loc, target_type, false);
1343                         return null;
1344                 }
1345
1346                 /// <summary>
1347                 ///   Performs the explicit numeric conversions
1348                 ///
1349                 /// There are a few conversions that are not part of the C# standard,
1350                 /// they were interim hacks in the C# compiler that were supposed to
1351                 /// become explicit operators in the UIntPtr class and IntPtr class,
1352                 /// but for historical reasons it did not happen, so the C# compiler
1353                 /// ended up with these special hacks.
1354                 ///
1355                 /// See bug 59800 for details.
1356                 ///
1357                 /// The conversion are:
1358                 ///   UIntPtr->SByte
1359                 ///   UIntPtr->Int16
1360                 ///   UIntPtr->Int32
1361                 ///   IntPtr->UInt64
1362                 ///   UInt64->IntPtr
1363                 ///   SByte->UIntPtr
1364                 ///   Int16->UIntPtr
1365                 ///
1366                 /// </summary>
1367                 public static Expression ExplicitNumericConversion (Expression expr, TypeSpec target_type)
1368                 {
1369                         TypeSpec expr_type = expr.Type;
1370                         TypeSpec real_target_type = target_type;
1371
1372                         if (expr_type == TypeManager.sbyte_type){
1373                                 //
1374                                 // From sbyte to byte, ushort, uint, ulong, char, uintptr
1375                                 //
1376                                 if (real_target_type == TypeManager.byte_type)
1377                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
1378                                 if (real_target_type == TypeManager.ushort_type)
1379                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
1380                                 if (real_target_type == TypeManager.uint32_type)
1381                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
1382                                 if (real_target_type == TypeManager.uint64_type)
1383                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
1384                                 if (real_target_type == TypeManager.char_type)
1385                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
1386
1387                                 // One of the built-in conversions that belonged in the class library
1388                                 if (real_target_type == TypeManager.uintptr_type){
1389                                         Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I1_U8);
1390
1391                                         return new OperatorCast (u8e, TypeManager.uintptr_type, true);
1392                                 }
1393                         } else if (expr_type == TypeManager.byte_type){
1394                                 //
1395                                 // From byte to sbyte and char
1396                                 //
1397                                 if (real_target_type == TypeManager.sbyte_type)
1398                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
1399                                 if (real_target_type == TypeManager.char_type)
1400                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
1401                         } else if (expr_type == TypeManager.short_type){
1402                                 //
1403                                 // From short to sbyte, byte, ushort, uint, ulong, char, uintptr
1404                                 //
1405                                 if (real_target_type == TypeManager.sbyte_type)
1406                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
1407                                 if (real_target_type == TypeManager.byte_type)
1408                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
1409                                 if (real_target_type == TypeManager.ushort_type)
1410                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
1411                                 if (real_target_type == TypeManager.uint32_type)
1412                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
1413                                 if (real_target_type == TypeManager.uint64_type)
1414                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
1415                                 if (real_target_type == TypeManager.char_type)
1416                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
1417
1418                                 // One of the built-in conversions that belonged in the class library
1419                                 if (real_target_type == TypeManager.uintptr_type){
1420                                         Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I2_U8);
1421
1422                                         return new OperatorCast (u8e, TypeManager.uintptr_type, true);
1423                                 }
1424                         } else if (expr_type == TypeManager.ushort_type){
1425                                 //
1426                                 // From ushort to sbyte, byte, short, char
1427                                 //
1428                                 if (real_target_type == TypeManager.sbyte_type)
1429                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
1430                                 if (real_target_type == TypeManager.byte_type)
1431                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
1432                                 if (real_target_type == TypeManager.short_type)
1433                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
1434                                 if (real_target_type == TypeManager.char_type)
1435                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
1436                         } else if (expr_type == TypeManager.int32_type){
1437                                 //
1438                                 // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
1439                                 //
1440                                 if (real_target_type == TypeManager.sbyte_type)
1441                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
1442                                 if (real_target_type == TypeManager.byte_type)
1443                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
1444                                 if (real_target_type == TypeManager.short_type)
1445                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
1446                                 if (real_target_type == TypeManager.ushort_type)
1447                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
1448                                 if (real_target_type == TypeManager.uint32_type)
1449                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
1450                                 if (real_target_type == TypeManager.uint64_type)
1451                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
1452                                 if (real_target_type == TypeManager.char_type)
1453                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
1454
1455                                 // One of the built-in conversions that belonged in the class library
1456                                 if (real_target_type == TypeManager.uintptr_type){
1457                                         Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I2_U8);
1458
1459                                         return new OperatorCast (u8e, TypeManager.uintptr_type, true);
1460                                 }
1461                         } else if (expr_type == TypeManager.uint32_type){
1462                                 //
1463                                 // From uint to sbyte, byte, short, ushort, int, char
1464                                 //
1465                                 if (real_target_type == TypeManager.sbyte_type)
1466                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
1467                                 if (real_target_type == TypeManager.byte_type)
1468                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
1469                                 if (real_target_type == TypeManager.short_type)
1470                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
1471                                 if (real_target_type == TypeManager.ushort_type)
1472                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
1473                                 if (real_target_type == TypeManager.int32_type)
1474                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
1475                                 if (real_target_type == TypeManager.char_type)
1476                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
1477                         } else if (expr_type == TypeManager.int64_type){
1478                                 //
1479                                 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1480                                 //
1481                                 if (real_target_type == TypeManager.sbyte_type)
1482                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
1483                                 if (real_target_type == TypeManager.byte_type)
1484                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
1485                                 if (real_target_type == TypeManager.short_type)
1486                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
1487                                 if (real_target_type == TypeManager.ushort_type)
1488                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
1489                                 if (real_target_type == TypeManager.int32_type)
1490                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
1491                                 if (real_target_type == TypeManager.uint32_type)
1492                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
1493                                 if (real_target_type == TypeManager.uint64_type)
1494                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
1495                                 if (real_target_type == TypeManager.char_type)
1496                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
1497                         } else if (expr_type == TypeManager.uint64_type){
1498                                 //
1499                                 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1500                                 //
1501                                 if (real_target_type == TypeManager.sbyte_type)
1502                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
1503                                 if (real_target_type == TypeManager.byte_type)
1504                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
1505                                 if (real_target_type == TypeManager.short_type)
1506                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
1507                                 if (real_target_type == TypeManager.ushort_type)
1508                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
1509                                 if (real_target_type == TypeManager.int32_type)
1510                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
1511                                 if (real_target_type == TypeManager.uint32_type)
1512                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
1513                                 if (real_target_type == TypeManager.int64_type)
1514                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
1515                                 if (real_target_type == TypeManager.char_type)
1516                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
1517
1518                                 // One of the built-in conversions that belonged in the class library
1519                                 if (real_target_type == TypeManager.intptr_type){
1520                                         return new OperatorCast (EmptyCast.Create (expr, TypeManager.int64_type),
1521                                                                  TypeManager.intptr_type, true);
1522                                 }
1523                         } else if (expr_type == TypeManager.char_type){
1524                                 //
1525                                 // From char to sbyte, byte, short
1526                                 //
1527                                 if (real_target_type == TypeManager.sbyte_type)
1528                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
1529                                 if (real_target_type == TypeManager.byte_type)
1530                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
1531                                 if (real_target_type == TypeManager.short_type)
1532                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
1533                         } else if (expr_type == TypeManager.float_type){
1534                                 //
1535                                 // From float to sbyte, byte, short,
1536                                 // ushort, int, uint, long, ulong, char
1537                                 // or decimal
1538                                 //
1539                                 if (real_target_type == TypeManager.sbyte_type)
1540                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
1541                                 if (real_target_type == TypeManager.byte_type)
1542                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
1543                                 if (real_target_type == TypeManager.short_type)
1544                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
1545                                 if (real_target_type == TypeManager.ushort_type)
1546                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
1547                                 if (real_target_type == TypeManager.int32_type)
1548                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
1549                                 if (real_target_type == TypeManager.uint32_type)
1550                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
1551                                 if (real_target_type == TypeManager.int64_type)
1552                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
1553                                 if (real_target_type == TypeManager.uint64_type)
1554                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
1555                                 if (real_target_type == TypeManager.char_type)
1556                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
1557                                 if (real_target_type == TypeManager.decimal_type)
1558                                         return new CastToDecimal (expr, true);
1559                         } else if (expr_type == TypeManager.double_type){
1560                                 //
1561                                 // From double to sbyte, byte, short,
1562                                 // ushort, int, uint, long, ulong,
1563                                 // char, float or decimal
1564                                 //
1565                                 if (real_target_type == TypeManager.sbyte_type)
1566                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
1567                                 if (real_target_type == TypeManager.byte_type)
1568                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
1569                                 if (real_target_type == TypeManager.short_type)
1570                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
1571                                 if (real_target_type == TypeManager.ushort_type)
1572                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
1573                                 if (real_target_type == TypeManager.int32_type)
1574                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
1575                                 if (real_target_type == TypeManager.uint32_type)
1576                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
1577                                 if (real_target_type == TypeManager.int64_type)
1578                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
1579                                 if (real_target_type == TypeManager.uint64_type)
1580                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
1581                                 if (real_target_type == TypeManager.char_type)
1582                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
1583                                 if (real_target_type == TypeManager.float_type)
1584                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
1585                                 if (real_target_type == TypeManager.decimal_type)
1586                                         return new CastToDecimal (expr, true);
1587                         } else if (expr_type == TypeManager.uintptr_type){
1588                                 //
1589                                 // Various built-in conversions that belonged in the class library
1590                                 //
1591                                 // from uintptr to sbyte, short, int32
1592                                 //
1593                                 if (real_target_type == TypeManager.sbyte_type){
1594                                         Expression uint32e = new OperatorCast (expr, TypeManager.uint32_type, true);
1595                                         return new ConvCast (uint32e, TypeManager.sbyte_type, ConvCast.Mode.U4_I1);
1596                                 }
1597                                 if (real_target_type == TypeManager.short_type){
1598                                         Expression uint32e = new OperatorCast (expr, TypeManager.uint32_type, true);
1599                                         return new ConvCast (uint32e, TypeManager.sbyte_type, ConvCast.Mode.U4_I2);
1600                                 }
1601                                 if (real_target_type == TypeManager.int32_type){
1602                                         return EmptyCast.Create (new OperatorCast (expr, TypeManager.uint32_type, true),
1603                                                               TypeManager.int32_type);
1604                                 }
1605                         } else if (expr_type == TypeManager.intptr_type){
1606                                 if (real_target_type == TypeManager.uint64_type){
1607                                         return EmptyCast.Create (new OperatorCast (expr, TypeManager.int64_type, true),
1608                                                               TypeManager.uint64_type);
1609                                 }
1610                         } else if (expr_type == TypeManager.decimal_type) {
1611                                 return new CastFromDecimal (expr, target_type).Resolve ();
1612                         }
1613                         return null;
1614                 }
1615
1616                 /// <summary>
1617                 ///  Returns whether an explicit reference conversion can be performed
1618                 ///  from source_type to target_type
1619                 /// </summary>
1620                 public static bool ExplicitReferenceConversionExists (TypeSpec source_type, TypeSpec target_type)
1621                 {
1622                         Expression e = ExplicitReferenceConversion (null, source_type, target_type);
1623                         if (e == null)
1624                                 return false;
1625
1626                         if (e == EmptyExpression.Null)
1627                                 return true;
1628
1629                         throw new InternalErrorException ("Invalid probing conversion result");
1630                 }
1631
1632                 /// <summary>
1633                 ///   Implements Explicit Reference conversions
1634                 /// </summary>
1635                 static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
1636                 {
1637                         //
1638                         // From object to a generic parameter
1639                         //
1640                         if (source_type == TypeManager.object_type && TypeManager.IsGenericParameter (target_type))
1641                                 return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1642
1643                         //
1644                         // Explicit type parameter conversion.
1645                         //
1646                         if (source_type.Kind == MemberKind.TypeParameter)
1647                                 return ExplicitTypeParameterConversion (source, source_type, target_type);
1648
1649                         bool target_is_value_type = TypeManager.IsStruct (target_type) || TypeManager.IsEnumType (target_type);
1650
1651                         //
1652                         // Unboxing conversion from System.ValueType to any non-nullable-value-type
1653                         //
1654                         if (source_type == TypeManager.value_type && target_is_value_type)
1655                                 return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1656
1657                         //
1658                         // From object or dynamic to any reference type or value type (unboxing)
1659                         //
1660                         if (source_type == TypeManager.object_type || source_type == InternalType.Dynamic)
1661                                 return
1662                                         source == null ? EmptyExpression.Null :
1663                                         target_is_value_type ? new UnboxCast (source, target_type) :
1664                                         source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) :
1665                                         new ClassCast (source, target_type);
1666
1667                         //
1668                         // From any class S to any class-type T, provided S is a base class of T
1669                         //
1670                         if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true))
1671                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1672
1673                         //
1674                         // From any interface-type S to to any class type T, provided T is not
1675                         // sealed, or provided T implements S.
1676                         //
1677                         if (source_type.IsInterface) {
1678                                 if (!target_type.IsSealed || target_type.ImplementsInterface (source_type)) {
1679                                         if (target_type.IsClass)
1680                                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1681
1682                                         //
1683                                         // Unboxing conversion from any interface-type to any non-nullable-value-type that
1684                                         // implements the interface-type
1685                                         //
1686                                         return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1687                                 }
1688
1689                                 //
1690                                 // From System.Collections.Generic.IList<T> and its base interfaces to a one-dimensional
1691                                 // array type S[], provided there is an implicit or explicit reference conversion from S to T.
1692                                 //
1693                                 var target_array = target_type as ArrayContainer;
1694                                 if (target_array != null && IList_To_Array (source_type, target_array))
1695                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1696
1697                                 return null;
1698                         }
1699
1700                         var source_array = source_type as ArrayContainer;
1701                         if (source_array != null) {
1702                                 var target_array = target_type as ArrayContainer;
1703                                 if (target_array != null) {
1704                                         //
1705                                         // From System.Array to any array-type
1706                                         //
1707                                         if (source_type == TypeManager.array_type)
1708                                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1709
1710                                         //
1711                                         // From an array type S with an element type Se to an array type T with an
1712                                         // element type Te provided all the following are true:
1713                                         //     * S and T differe only in element type, in other words, S and T
1714                                         //       have the same number of dimensions.
1715                                         //     * Both Se and Te are reference types
1716                                         //     * An explicit reference conversions exist from Se to Te
1717                                         //
1718                                         if (source_array.Rank == target_array.Rank) {
1719
1720                                                 source_type = source_array.Element;
1721                                                 if (!TypeManager.IsReferenceType (source_type))
1722                                                         return null;
1723
1724                                                 var target_element = target_array.Element;
1725                                                 if (!TypeManager.IsReferenceType (target_element))
1726                                                         return null;
1727
1728                                                 if (ExplicitReferenceConversionExists (source_type, target_element))
1729                                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1730                                                         
1731                                                 return null;
1732                                         }
1733                                 }
1734
1735                                 //
1736                                 // From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, 
1737                                 // provided that there is an explicit reference conversion from S to T
1738                                 //
1739                                 if (ArrayToIList (source_array, target_type, true))
1740                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1741
1742                                 return null;
1743                         }
1744
1745                         //
1746                         // From any class type S to any interface T, provides S is not sealed
1747                         // and provided S does not implement T.
1748                         //
1749                         if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type)) {
1750                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1751                         }
1752
1753                         //
1754                         // From System delegate to any delegate-type
1755                         //
1756                         if (source_type == TypeManager.delegate_type && TypeManager.IsDelegateType (target_type))
1757                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1758
1759                         //
1760                         // From variant generic delegate to same variant generic delegate type
1761                         //
1762                         if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) {
1763                                 var tparams = source_type.MemberDefinition.TypeParameters;
1764                                 var targs_src = source_type.TypeArguments;
1765                                 var targs_dst = target_type.TypeArguments;
1766                                 int i;
1767                                 for (i = 0; i < tparams.Length; ++i) {
1768                                         //
1769                                         // If TP is invariant, types have to be identical
1770                                         //
1771                                         if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i]))
1772                                                 continue;
1773
1774                                         if (tparams[i].Variance == Variance.Covariant) {
1775                                                 //
1776                                                 //If TP is covariant, an implicit or explicit identity or reference conversion is required
1777                                                 //
1778                                                 if (ImplicitReferenceConversionExists (new EmptyExpression (targs_src[i]), targs_dst[i]))
1779                                                         continue;
1780
1781                                                 if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1782                                                         continue;
1783
1784                                         } else if (tparams[i].Variance == Variance.Contravariant) {
1785                                                 //
1786                                                 //If TP is contravariant, both are either identical or reference types
1787                                                 //
1788                                                 if (TypeManager.IsReferenceType (targs_src[i]) && TypeManager.IsReferenceType (targs_dst[i]))
1789                                                         continue;
1790                                         }
1791
1792                                         break;
1793                                 }
1794
1795                                 if (i == tparams.Length)
1796                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1797                         }
1798
1799                         return null;
1800                 }
1801
1802                 /// <summary>
1803                 ///   Performs an explicit conversion of the expression `expr' whose
1804                 ///   type is expr.Type to `target_type'.
1805                 /// </summary>
1806                 static public Expression ExplicitConversionCore (ResolveContext ec, Expression expr,
1807                                                                  TypeSpec target_type, Location loc)
1808                 {
1809                         TypeSpec expr_type = expr.Type;
1810
1811                         // Explicit conversion includes implicit conversion and it used for enum underlying types too
1812                         Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true);
1813                         if (ne != null)
1814                                 return ne;
1815
1816                         if (TypeManager.IsEnumType (expr_type)) {
1817                                 TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1818                                 Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type));
1819                                 if (underlying.Type == real_target)
1820                                         ne = underlying;
1821
1822                                 if (ne == null)
1823                                         ne = ImplicitNumericConversion (underlying, real_target);
1824
1825                                 if (ne == null)
1826                                         ne = ExplicitNumericConversion (underlying, real_target);
1827
1828                                 //
1829                                 // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
1830                                 //
1831                                 if (ne == null && (real_target == TypeManager.intptr_type || real_target == TypeManager.uintptr_type))
1832                                         ne = ExplicitUserConversion (ec, underlying, real_target, loc);
1833
1834                                 return ne != null ? EmptyCast.Create (ne, target_type) : null;
1835                         }
1836
1837                         if (TypeManager.IsEnumType (target_type)) {
1838                                 //
1839                                 // System.Enum can be unboxed to any enum-type
1840                                 //
1841                                 if (expr_type == TypeManager.enum_type)
1842                                         return new UnboxCast (expr, target_type);
1843
1844                                 TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1845
1846                                 if (expr_type == real_target)
1847                                         return EmptyCast.Create (expr, target_type);
1848
1849                                 ne = ImplicitNumericConversion (expr, real_target);
1850                                 if (ne != null)
1851                                         return EmptyCast.Create (ne, target_type);
1852
1853                                 ne = ExplicitNumericConversion (expr, real_target);
1854                                 if (ne != null)
1855                                         return EmptyCast.Create (ne, target_type);
1856
1857                                 //
1858                                 // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
1859                                 //
1860                                 if (expr_type == TypeManager.intptr_type || expr_type == TypeManager.uintptr_type) {
1861                                         ne = ExplicitUserConversion (ec, expr, real_target, loc);
1862                                         if (ne != null)
1863                                                 return ExplicitConversionCore (ec, ne, target_type, loc);
1864                                 }
1865                         } else {
1866                                 ne = ExplicitNumericConversion (expr, target_type);
1867                                 if (ne != null)
1868                                         return ne;
1869                         }
1870
1871                         //
1872                         // Skip the ExplicitReferenceConversion because we can not convert
1873                         // from Null to a ValueType, and ExplicitReference wont check against
1874                         // null literal explicitly
1875                         //
1876                         if (expr_type != InternalType.Null) {
1877                                 ne = ExplicitReferenceConversion (expr, expr_type, target_type);
1878                                 if (ne != null)
1879                                         return ne;
1880                         }
1881
1882                         if (ec.IsUnsafe){
1883                                 ne = ExplicitUnsafe (expr, target_type);
1884                                 if (ne != null)
1885                                         return ne;
1886                         }
1887                         
1888                         return null;
1889                 }
1890
1891                 public static Expression ExplicitUnsafe (Expression expr, TypeSpec target_type)
1892                 {
1893                         TypeSpec expr_type = expr.Type;
1894
1895                         if (target_type.IsPointer){
1896                                 if (expr_type.IsPointer)
1897                                         return EmptyCast.Create (expr, target_type);
1898
1899                                 if (expr_type == TypeManager.sbyte_type ||
1900                                         expr_type == TypeManager.short_type ||
1901                                         expr_type == TypeManager.int32_type)
1902                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
1903
1904                                 if (expr_type == TypeManager.ushort_type ||
1905                                         expr_type == TypeManager.uint32_type ||
1906                                         expr_type == TypeManager.byte_type)
1907                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
1908
1909                                 if (expr_type == TypeManager.int64_type)
1910                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I);
1911
1912                                 if (expr_type == TypeManager.uint64_type)
1913                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I);
1914                         }
1915
1916                         if (expr_type.IsPointer){
1917                                 if (target_type == TypeManager.sbyte_type)
1918                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1919                                 if (target_type == TypeManager.byte_type)
1920                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1921                                 if (target_type == TypeManager.short_type)
1922                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1923                                 if (target_type == TypeManager.ushort_type)
1924                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1925                                 if (target_type == TypeManager.int32_type)
1926                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
1927                                 if (target_type == TypeManager.uint32_type)
1928                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
1929                                 if (target_type == TypeManager.int64_type)
1930                                         return new ConvCast (expr, target_type, ConvCast.Mode.I_I8);
1931                                 if (target_type == TypeManager.uint64_type)
1932                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
1933                         }
1934                         return null;
1935                 }
1936
1937                 /// <summary>
1938                 ///   Same as ExplicitConversion, only it doesn't include user defined conversions
1939                 /// </summary>
1940                 static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr,
1941                                                                      TypeSpec target_type, Location l)
1942                 {
1943                         int errors = ec.Report.Errors;
1944                         Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
1945                         if (ec.Report.Errors > errors)
1946                                 return null;
1947
1948                         if (ne != null)
1949                                 return ne;
1950
1951                         ne = ExplicitNumericConversion (expr, target_type);
1952                         if (ne != null)
1953                                 return ne;
1954
1955                         ne = ExplicitReferenceConversion (expr, expr.Type, target_type);
1956                         if (ne != null)
1957                                 return ne;
1958
1959                         if (ec.IsUnsafe && expr.Type == TypeManager.void_ptr_type && target_type.IsPointer)
1960                                 return EmptyCast.Create (expr, target_type);
1961
1962                         expr.Error_ValueCannotBeConverted (ec, l, target_type, true);
1963                         return null;
1964                 }
1965
1966                 /// <summary>
1967                 ///   Performs an explicit conversion of the expression `expr' whose
1968                 ///   type is expr.Type to `target_type'.
1969                 /// </summary>
1970                 static public Expression ExplicitConversion (ResolveContext ec, Expression expr,
1971                         TypeSpec target_type, Location loc)
1972                 {
1973                         Expression e = ExplicitConversionCore (ec, expr, target_type, loc);
1974                         if (e != null) {
1975                                 //
1976                                 // Don't eliminate explicit precission casts
1977                                 //
1978                                 if (e == expr) {
1979                                         if (target_type == TypeManager.float_type)
1980                                                 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
1981                                         
1982                                         if (target_type == TypeManager.double_type)
1983                                                 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
1984                                 }
1985                                         
1986                                 return e;
1987                         }
1988
1989                         TypeSpec expr_type = expr.Type;
1990                         if (TypeManager.IsNullableType (target_type)) {
1991                                 if (TypeManager.IsNullableType (expr_type)) {
1992                                         TypeSpec target = Nullable.NullableInfo.GetUnderlyingType (target_type);
1993                                         Expression unwrap = Nullable.Unwrap.Create (expr);
1994                                         e = ExplicitConversion (ec, unwrap, target, expr.Location);
1995                                         if (e == null)
1996                                                 return null;
1997
1998                                         return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec);
1999                                 } else if (expr_type == TypeManager.object_type) {
2000                                         return new UnboxCast (expr, target_type);
2001                                 } else {
2002                                         TypeSpec target = TypeManager.GetTypeArguments (target_type) [0];
2003
2004                                         e = ExplicitConversionCore (ec, expr, target, loc);
2005                                         if (e != null)
2006                                                 return Nullable.Wrap.Create (e, target_type);
2007                                 }
2008                         } else if (TypeManager.IsNullableType (expr_type)) {
2009                                 e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
2010                                 if (e != null)
2011                                         return e;
2012
2013                                 e = Nullable.Unwrap.Create (expr, false);                       
2014                                 e = ExplicitConversionCore (ec, e, target_type, loc);
2015                                 if (e != null)
2016                                         return EmptyCast.Create (e, target_type);
2017                         }
2018                         
2019                         e = ExplicitUserConversion (ec, expr, target_type, loc);
2020                         if (e != null)
2021                                 return e;                       
2022
2023                         expr.Error_ValueCannotBeConverted (ec, loc, target_type, true);
2024                         return null;
2025                 }
2026         }
2027 }