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