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