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