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