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