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