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