Wrap always_inline and noinline attributes in compiler checks and use MSVC equivalent.
[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 unwrapping conversion S? -> T for non-reference types
1094                                 if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) {
1095                                         source_type_expr = source;
1096                                 } else {
1097                                         source_type_expr = Nullable.Unwrap.Create (source);
1098                                         source_type = source_type_expr.Type;
1099                                 }
1100                         } else {
1101                                 source_type_expr = source;
1102                         }
1103
1104                         if (target_type.IsNullableType)
1105                                 target_type = Nullable.NullableInfo.GetUnderlyingType (target_type);
1106
1107                         // Only these containers can contain a user defined implicit or explicit operators
1108                         const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter;
1109
1110                         if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1111                                 bool declared_only = source_type.IsStruct;
1112
1113                                 var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only);
1114                                 if (operators != null) {
1115                                         FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1116                                 }
1117
1118                                 if (!implicitOnly) {
1119                                         operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only);
1120                                         if (operators != null) {
1121                                                 FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1122                                         }
1123                                 }
1124                         }
1125
1126                         if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1127                                 bool declared_only = target.IsStruct || implicitOnly;
1128
1129                                 var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only);
1130                                 if (operators != null) {
1131                                         FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
1132                                 }
1133
1134                                 if (!implicitOnly) {
1135                                         operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only);
1136                                         if (operators != null) {
1137                                                 FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
1138                                         }
1139                                 }
1140                         }
1141
1142                         if (candidates == null)
1143                                 return null;
1144
1145                         //
1146                         // Find the most specific conversion operator
1147                         //
1148                         MethodSpec most_specific_operator;
1149                         TypeSpec s_x, t_x;
1150                         if (candidates.Count == 1) {
1151                                 most_specific_operator = candidates[0];
1152                                 s_x = most_specific_operator.Parameters.Types[0];
1153                                 t_x = most_specific_operator.ReturnType;
1154                         } else {
1155                                 //
1156                                 // Pass original source type to find the best match against input type and
1157                                 // not the unwrapped expression
1158                                 //
1159                                 s_x = FindMostSpecificSource (candidates, source.Type, source_type_expr, !implicitOnly);
1160                                 if (s_x == null)
1161                                         return null;
1162
1163                                 t_x = FindMostSpecificTarget (candidates, target, !implicitOnly);
1164                                 if (t_x == null)
1165                                         return null;
1166
1167                                 most_specific_operator = null;
1168                                 for (int i = 0; i < candidates.Count; ++i) {
1169                                         if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) {
1170                                                 most_specific_operator = candidates[i];
1171                                                 break;
1172                                         }
1173                                 }
1174
1175                                 if (most_specific_operator == null) {
1176                                         MethodSpec ambig_arg = null;
1177                                         foreach (var candidate in candidates) {
1178                                                 if (candidate.ReturnType == t_x)
1179                                                         most_specific_operator = candidate;
1180                                                 else if (candidate.Parameters.Types[0] == s_x)
1181                                                         ambig_arg = candidate;
1182                                         }
1183
1184                                         ec.Report.Error (457, loc,
1185                                                 "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'",
1186                                                 ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (),
1187                                                 source.Type.GetSignatureForError (), target.GetSignatureForError ());
1188
1189                                         return ErrorExpression.Instance;
1190                                 }
1191                         }
1192
1193                         //
1194                         // Convert input type when it's different to best operator argument
1195                         //
1196                         if (s_x != source_type) {
1197                                 var c = source as Constant;
1198                                 if (c != null) {
1199                                         source = c.TryReduce (ec, s_x);
1200                                         if (source == null)
1201                                                 c = null;
1202                                 }
1203
1204                                 if (c == null) {
1205                                         source = implicitOnly ?
1206                                                 ImplicitConversionStandard (ec, source_type_expr, s_x, loc) :
1207                                                 ExplicitConversionStandard (ec, source_type_expr, s_x, loc);
1208                                 }
1209                         } else {
1210                                 source = source_type_expr;
1211                         }
1212
1213                         source = new UserCast (most_specific_operator, source, loc).Resolve (ec);
1214
1215                         //
1216                         // Convert result type when it's different to best operator return type
1217                         //
1218                         if (t_x != target_type) {
1219                                 //
1220                                 // User operator is of T?, no need to lift it
1221                                 //
1222                                 if (t_x == target && t_x.IsNullableType)
1223                                         return source;
1224
1225                                 source = implicitOnly ?
1226                                         ImplicitConversionStandard (ec, source, target_type, loc) :
1227                                         ExplicitConversionStandard (ec, source, target_type, loc);
1228
1229                                 if (source == null)
1230                                         return null;
1231                         }
1232
1233                         //
1234                         // Source expression is of nullable type, lift the result in the case it's null and
1235                         // not nullable/lifted user operator is used
1236                         //
1237                         if (source_type_expr is Nullable.Unwrap && !s_x.IsNullableType && (TypeSpec.IsReferenceType (target) || target_type != target))
1238                                 source = new Nullable.Lifted (source, source_type_expr, target).Resolve (ec);
1239                         else if (target_type != target)
1240                                 source = Nullable.Wrap.Create (source, target);
1241
1242                         return source;
1243                 }
1244
1245                 /// <summary>
1246                 ///   Converts implicitly the resolved expression `expr' into the
1247                 ///   `target_type'.  It returns a new expression that can be used
1248                 ///   in a context that expects a `target_type'.
1249                 /// </summary>
1250                 static public Expression ImplicitConversion (ResolveContext ec, Expression expr,
1251                                                              TypeSpec target_type, Location loc)
1252                 {
1253                         Expression e;
1254
1255                         if (target_type == null)
1256                                 throw new Exception ("Target type is null");
1257
1258                         e = ImplicitConversionStandard (ec, expr, target_type, loc);
1259                         if (e != null)
1260                                 return e;
1261
1262                         e = ImplicitUserConversion (ec, expr, target_type, loc);
1263                         if (e != null)
1264                                 return e;
1265
1266                         return null;
1267                 }
1268
1269
1270                 /// <summary>
1271                 ///   Attempts to apply the `Standard Implicit
1272                 ///   Conversion' rules to the expression `expr' into
1273                 ///   the `target_type'.  It returns a new expression
1274                 ///   that can be used in a context that expects a
1275                 ///   `target_type'.
1276                 ///
1277                 ///   This is different from `ImplicitConversion' in that the
1278                 ///   user defined implicit conversions are excluded.
1279                 /// </summary>
1280                 static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr,
1281                                                                      TypeSpec target_type, Location loc)
1282                 {
1283                         return ImplicitConversionStandard (ec, expr, target_type, loc, false);
1284                 }
1285
1286                 static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast)
1287                 {
1288                         if (expr.eclass == ExprClass.MethodGroup){
1289                                 if (!target_type.IsDelegate){
1290                                         return null;
1291                                 }
1292
1293                                 //
1294                                 // Only allow anonymous method conversions on post ISO_1
1295                                 //
1296                                 if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){
1297                                         MethodGroupExpr mg = expr as MethodGroupExpr;
1298                                         if (mg != null)
1299                                                 return ImplicitDelegateCreation.Create (
1300                                                         ec, mg, target_type, loc);
1301                                 }
1302                         }
1303
1304                         TypeSpec expr_type = expr.Type;
1305                         Expression e;
1306
1307                         if (expr_type == target_type) {
1308                                 if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod)
1309                                         return expr;
1310                                 return null;
1311                         }
1312
1313                         if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1314                                 switch (target_type.Kind) {
1315                                 case MemberKind.ArrayType:
1316                                 case MemberKind.Class:
1317                                         if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object)
1318                                                 return EmptyCast.Create (expr, target_type);
1319
1320                                         goto case MemberKind.Struct;
1321                                 case MemberKind.Struct:
1322                                 case MemberKind.Delegate:
1323                                 case MemberKind.Enum:
1324                                 case MemberKind.Interface:
1325                                 case MemberKind.TypeParameter:
1326                                         Arguments args = new Arguments (1);
1327                                         args.Add (new Argument (expr));
1328                                         return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec);
1329                                 }
1330
1331                                 return null;
1332                         }
1333
1334                         if (target_type.IsNullableType)
1335                                 return ImplicitNulableConversion (ec, expr, target_type);
1336
1337                         //
1338                         // Attempt to do the implicit constant expression conversions
1339                         //
1340                         Constant c = expr as Constant;
1341                         if (c != null) {
1342                                 try {
1343                                         c = c.ConvertImplicitly (target_type);
1344                                 } catch {
1345                                         throw new InternalErrorException ("Conversion error", loc);
1346                                 }
1347                                 if (c != null)
1348                                         return c;
1349                         }
1350
1351                         e = ImplicitNumericConversion (expr, expr_type, target_type);
1352                         if (e != null)
1353                                 return e;
1354
1355                         e = ImplicitReferenceConversion (expr, target_type, explicit_cast);
1356                         if (e != null)
1357                                 return e;
1358
1359                         e = ImplicitBoxingConversion (expr, expr_type, target_type);
1360                         if (e != null)
1361                                 return e;
1362
1363                         if (expr is IntegralConstant && target_type.IsEnum){
1364                                 var i = (IntegralConstant) expr;
1365                                 //
1366                                 // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
1367                                 //
1368                                 // An implicit enumeration conversion permits the decimal-integer-literal 0
1369                                 // to be converted to any enum-type and to any nullable-type whose underlying
1370                                 // type is an enum-type
1371                                 //
1372                                 if (i.IsZeroInteger) {
1373                                         // Recreate 0 literal to remove any collected conversions
1374                                         return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type);
1375                                 }
1376                         }
1377
1378                         if (ec.IsUnsafe) {
1379                                 var target_pc = target_type as PointerContainer;
1380                                 if (target_pc != null) {
1381                                         if (expr_type.IsPointer) {
1382                                                 //
1383                                                 // Pointer types are same when they have same element types
1384                                                 //
1385                                                 if (expr_type == target_pc)
1386                                                         return expr;
1387
1388                                                 if (target_pc.Element.Kind == MemberKind.Void)
1389                                                         return EmptyCast.Create (expr, target_type);
1390
1391                                                 //return null;
1392                                         }
1393
1394                                         if (expr_type == InternalType.NullLiteral)
1395                                                 return new NullPointer (target_type, loc);
1396                                 }
1397                         }
1398
1399                         if (expr_type == InternalType.AnonymousMethod){
1400                                 AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
1401                                 Expression am = ame.Compatible (ec, target_type);
1402                                 if (am != null)
1403                                         return am.Resolve (ec);
1404                         }
1405
1406                         if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec)
1407                                 return expr;
1408
1409                         //
1410                         // dynamic erasure conversion on value types
1411                         //
1412                         if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
1413                                 return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type);
1414
1415                         return null;
1416                 }
1417
1418                 /// <summary>
1419                 ///   Attempts to implicitly convert `source' into `target_type', using
1420                 ///   ImplicitConversion.  If there is no implicit conversion, then
1421                 ///   an error is signaled
1422                 /// </summary>
1423                 static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
1424                                                                      TypeSpec target_type, Location loc)
1425                 {
1426                         Expression e = ImplicitConversion (ec, source, target_type, loc);
1427                         if (e != null)
1428                                 return e;
1429
1430                         source.Error_ValueCannotBeConverted (ec, target_type, false);
1431                         return null;
1432                 }
1433
1434                 /// <summary>
1435                 ///   Performs the explicit numeric conversions
1436                 ///
1437                 /// There are a few conversions that are not part of the C# standard,
1438                 /// they were interim hacks in the C# compiler that were supposed to
1439                 /// become explicit operators in the UIntPtr class and IntPtr class,
1440                 /// but for historical reasons it did not happen, so the C# compiler
1441                 /// ended up with these special hacks.
1442                 ///
1443                 /// See bug 59800 for details.
1444                 ///
1445                 /// The conversion are:
1446                 ///   UIntPtr->SByte
1447                 ///   UIntPtr->Int16
1448                 ///   UIntPtr->Int32
1449                 ///   IntPtr->UInt64
1450                 ///   UInt64->IntPtr
1451                 ///   SByte->UIntPtr
1452                 ///   Int16->UIntPtr
1453                 ///
1454                 /// </summary>
1455                 public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type)
1456                 {
1457                         // Not all predefined explicit numeric conversion are
1458                         // defined here, for some of them (mostly IntPtr/UIntPtr) we
1459                         // defer to user-operator handling which is now perfect but
1460                         // works for now
1461                         //
1462                         // LAMESPEC: Undocumented IntPtr/UIntPtr conversions
1463                         // IntPtr -> uint uses int
1464                         // UIntPtr -> long uses ulong
1465                         //
1466
1467                         switch (expr.Type.BuiltinType) {
1468                         case BuiltinTypeSpec.Type.SByte:
1469                                 //
1470                                 // From sbyte to byte, ushort, uint, ulong, char, uintptr
1471                                 //
1472                                 switch (target_type.BuiltinType) {
1473                                 case BuiltinTypeSpec.Type.Byte:
1474                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
1475                                 case BuiltinTypeSpec.Type.UShort:
1476                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
1477                                 case BuiltinTypeSpec.Type.UInt:
1478                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
1479                                 case BuiltinTypeSpec.Type.ULong:
1480                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
1481                                 case BuiltinTypeSpec.Type.Char:
1482                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
1483
1484                                 // One of the built-in conversions that belonged in the class library
1485                                 case BuiltinTypeSpec.Type.UIntPtr:
1486                                         return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true);
1487                                 }
1488                                 break;
1489                         case BuiltinTypeSpec.Type.Byte:
1490                                 //
1491                                 // From byte to sbyte and char
1492                                 //
1493                                 switch (target_type.BuiltinType) {
1494                                 case BuiltinTypeSpec.Type.SByte:
1495                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
1496                                 case BuiltinTypeSpec.Type.Char:
1497                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
1498                                 }
1499                                 break;
1500                         case BuiltinTypeSpec.Type.Short:
1501                                 //
1502                                 // From short to sbyte, byte, ushort, uint, ulong, char, uintptr
1503                                 //
1504                                 switch (target_type.BuiltinType) {
1505                                 case BuiltinTypeSpec.Type.SByte:
1506                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
1507                                 case BuiltinTypeSpec.Type.Byte:
1508                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
1509                                 case BuiltinTypeSpec.Type.UShort:
1510                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
1511                                 case BuiltinTypeSpec.Type.UInt:
1512                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
1513                                 case BuiltinTypeSpec.Type.ULong:
1514                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
1515                                 case BuiltinTypeSpec.Type.Char:
1516                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
1517
1518                                 // One of the built-in conversions that belonged in the class library
1519                                 case BuiltinTypeSpec.Type.UIntPtr:
1520                                         return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1521                                 }
1522                                 break;
1523                         case BuiltinTypeSpec.Type.UShort:
1524                                 //
1525                                 // From ushort to sbyte, byte, short, char
1526                                 //
1527                                 switch (target_type.BuiltinType) {
1528                                 case BuiltinTypeSpec.Type.SByte:
1529                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
1530                                 case BuiltinTypeSpec.Type.Byte:
1531                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
1532                                 case BuiltinTypeSpec.Type.Short:
1533                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
1534                                 case BuiltinTypeSpec.Type.Char:
1535                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
1536                                 }
1537                                 break;
1538                         case BuiltinTypeSpec.Type.Int:
1539                                 //
1540                                 // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
1541                                 //
1542                                 switch (target_type.BuiltinType) {
1543                                 case BuiltinTypeSpec.Type.SByte:
1544                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
1545                                 case BuiltinTypeSpec.Type.Byte:
1546                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
1547                                 case BuiltinTypeSpec.Type.Short:
1548                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
1549                                 case BuiltinTypeSpec.Type.UShort:
1550                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
1551                                 case BuiltinTypeSpec.Type.UInt:
1552                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
1553                                 case BuiltinTypeSpec.Type.ULong:
1554                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
1555                                 case BuiltinTypeSpec.Type.Char:
1556                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
1557
1558                                 // One of the built-in conversions that belonged in the class library
1559                                 case BuiltinTypeSpec.Type.UIntPtr:
1560                                         return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1561                                 }
1562                                 break;
1563                         case BuiltinTypeSpec.Type.UInt:
1564                                 //
1565                                 // From uint to sbyte, byte, short, ushort, int, char
1566                                 //
1567                                 switch (target_type.BuiltinType) {
1568                                 case BuiltinTypeSpec.Type.SByte:
1569                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
1570                                 case BuiltinTypeSpec.Type.Byte:
1571                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
1572                                 case BuiltinTypeSpec.Type.Short:
1573                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
1574                                 case BuiltinTypeSpec.Type.UShort:
1575                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
1576                                 case BuiltinTypeSpec.Type.Int:
1577                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
1578                                 case BuiltinTypeSpec.Type.Char:
1579                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
1580                                 }
1581                                 break;
1582                         case BuiltinTypeSpec.Type.Long:
1583                                 //
1584                                 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1585                                 //
1586                                 switch (target_type.BuiltinType) {
1587                                 case BuiltinTypeSpec.Type.SByte:
1588                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
1589                                 case BuiltinTypeSpec.Type.Byte:
1590                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
1591                                 case BuiltinTypeSpec.Type.Short:
1592                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
1593                                 case BuiltinTypeSpec.Type.UShort:
1594                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
1595                                 case BuiltinTypeSpec.Type.Int:
1596                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
1597                                 case BuiltinTypeSpec.Type.UInt:
1598                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
1599                                 case BuiltinTypeSpec.Type.ULong:
1600                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
1601                                 case BuiltinTypeSpec.Type.Char:
1602                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
1603                                 }
1604                                 break;
1605                         case BuiltinTypeSpec.Type.ULong:
1606                                 //
1607                                 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1608                                 //
1609                                 switch (target_type.BuiltinType) {
1610                                 case BuiltinTypeSpec.Type.SByte:
1611                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
1612                                 case BuiltinTypeSpec.Type.Byte:
1613                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
1614                                 case BuiltinTypeSpec.Type.Short:
1615                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
1616                                 case BuiltinTypeSpec.Type.UShort:
1617                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
1618                                 case BuiltinTypeSpec.Type.Int:
1619                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
1620                                 case BuiltinTypeSpec.Type.UInt:
1621                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
1622                                 case BuiltinTypeSpec.Type.Long:
1623                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
1624                                 case BuiltinTypeSpec.Type.Char:
1625                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
1626
1627                                 // One of the built-in conversions that belonged in the class library
1628                                 case BuiltinTypeSpec.Type.IntPtr:
1629                                         return new OperatorCast (EmptyCast.Create (expr, rc.BuiltinTypes.Long), target_type, true);
1630                                 }
1631                                 break;
1632                         case BuiltinTypeSpec.Type.Char:
1633                                 //
1634                                 // From char to sbyte, byte, short
1635                                 //
1636                                 switch (target_type.BuiltinType) {
1637                                 case BuiltinTypeSpec.Type.SByte:
1638                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
1639                                 case BuiltinTypeSpec.Type.Byte:
1640                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
1641                                 case BuiltinTypeSpec.Type.Short:
1642                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
1643                                 }
1644                                 break;
1645                         case BuiltinTypeSpec.Type.Float:
1646                                 //
1647                                 // From float to sbyte, byte, short,
1648                                 // ushort, int, uint, long, ulong, char
1649                                 // or decimal
1650                                 //
1651                                 switch (target_type.BuiltinType) {
1652                                 case BuiltinTypeSpec.Type.SByte:
1653                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
1654                                 case BuiltinTypeSpec.Type.Byte:
1655                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
1656                                 case BuiltinTypeSpec.Type.Short:
1657                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
1658                                 case BuiltinTypeSpec.Type.UShort:
1659                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
1660                                 case BuiltinTypeSpec.Type.Int:
1661                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
1662                                 case BuiltinTypeSpec.Type.UInt:
1663                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
1664                                 case BuiltinTypeSpec.Type.Long:
1665                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
1666                                 case BuiltinTypeSpec.Type.ULong:
1667                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
1668                                 case BuiltinTypeSpec.Type.Char:
1669                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
1670                                 case BuiltinTypeSpec.Type.Decimal:
1671                                         return new OperatorCast (expr, target_type, true);
1672                                 }
1673                                 break;
1674                         case BuiltinTypeSpec.Type.Double:
1675                                 //
1676                                 // From double to sbyte, byte, short,
1677                                 // ushort, int, uint, long, ulong,
1678                                 // char, float or decimal
1679                                 //
1680                                 switch (target_type.BuiltinType) {
1681                                 case BuiltinTypeSpec.Type.SByte:
1682                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
1683                                 case BuiltinTypeSpec.Type.Byte:
1684                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
1685                                 case BuiltinTypeSpec.Type.Short:
1686                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
1687                                 case BuiltinTypeSpec.Type.UShort:
1688                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
1689                                 case BuiltinTypeSpec.Type.Int:
1690                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
1691                                 case BuiltinTypeSpec.Type.UInt:
1692                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
1693                                 case BuiltinTypeSpec.Type.Long:
1694                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
1695                                 case BuiltinTypeSpec.Type.ULong:
1696                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
1697                                 case BuiltinTypeSpec.Type.Char:
1698                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
1699                                 case BuiltinTypeSpec.Type.Float:
1700                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
1701                                 case BuiltinTypeSpec.Type.Decimal:
1702                                         return new OperatorCast (expr, target_type, true);
1703                                 }
1704                                 break;
1705                         case BuiltinTypeSpec.Type.UIntPtr:
1706                                 //
1707                                 // Various built-in conversions that belonged in the class library
1708                                 //
1709                                 // from uintptr to sbyte, short, int32
1710                                 //
1711                                 switch (target_type.BuiltinType) {
1712                                 case BuiltinTypeSpec.Type.SByte:
1713                                         return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I1);
1714                                 case BuiltinTypeSpec.Type.Short:
1715                                         return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I2);
1716                                 case BuiltinTypeSpec.Type.Int:
1717                                         return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type);
1718                                 case BuiltinTypeSpec.Type.UInt:
1719                                         return new OperatorCast (expr, expr.Type, target_type, true);
1720                                 case BuiltinTypeSpec.Type.Long:
1721                                         return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.ULong, true), target_type);
1722                                 }
1723                                 break;
1724                         case BuiltinTypeSpec.Type.IntPtr:
1725                                 if (target_type.BuiltinType == BuiltinTypeSpec.Type.UInt)
1726                                         return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Int, true), target_type);
1727                                 if (target_type.BuiltinType == BuiltinTypeSpec.Type.ULong)
1728                                         return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Long, true), target_type);
1729                                 
1730                                 break;
1731                         case BuiltinTypeSpec.Type.Decimal:
1732                                 // From decimal to sbyte, byte, short,
1733                                 // ushort, int, uint, long, ulong, char,
1734                                 // float, or double
1735                                 switch (target_type.BuiltinType) {
1736                                 case BuiltinTypeSpec.Type.SByte:
1737                                 case BuiltinTypeSpec.Type.Byte:
1738                                 case BuiltinTypeSpec.Type.Short:
1739                                 case BuiltinTypeSpec.Type.UShort:
1740                                 case BuiltinTypeSpec.Type.Int:
1741                                 case BuiltinTypeSpec.Type.UInt:
1742                                 case BuiltinTypeSpec.Type.Long:
1743                                 case BuiltinTypeSpec.Type.ULong:
1744                                 case BuiltinTypeSpec.Type.Char:
1745                                 case BuiltinTypeSpec.Type.Float:
1746                                 case BuiltinTypeSpec.Type.Double:
1747                                         return new OperatorCast (expr, expr.Type, target_type, true);
1748                                 }
1749
1750                                 break;
1751                         }
1752
1753                         return null;
1754                 }
1755
1756                 /// <summary>
1757                 ///  Returns whether an explicit reference conversion can be performed
1758                 ///  from source_type to target_type
1759                 /// </summary>
1760                 public static bool ExplicitReferenceConversionExists (TypeSpec source_type, TypeSpec target_type)
1761                 {
1762                         Expression e = ExplicitReferenceConversion (null, source_type, target_type);
1763                         if (e == null)
1764                                 return false;
1765
1766                         if (e == EmptyExpression.Null)
1767                                 return true;
1768
1769                         throw new InternalErrorException ("Invalid probing conversion result");
1770                 }
1771
1772                 /// <summary>
1773                 ///   Implements Explicit Reference conversions
1774                 /// </summary>
1775                 static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
1776                 {
1777                         //
1778                         // From object to a generic parameter
1779                         //
1780                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type))
1781                                 return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1782
1783                         //
1784                         // Explicit type parameter conversion.
1785                         //
1786                         if (source_type.Kind == MemberKind.TypeParameter)
1787                                 return ExplicitTypeParameterConversion (source, source_type, target_type);
1788
1789                         bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum;
1790
1791                         //
1792                         // Unboxing conversion from System.ValueType to any non-nullable-value-type
1793                         //
1794                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type)
1795                                 return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1796
1797                         //
1798                         // From object or dynamic to any reference type or value type (unboxing)
1799                         //
1800                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1801                                 if (target_type.IsPointer)
1802                                         return null;
1803
1804                                 return
1805                                         source == null ? EmptyExpression.Null :
1806                                         target_is_value_type ? new UnboxCast (source, target_type) :
1807                                         source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) :
1808                                         new ClassCast (source, target_type);
1809                         }
1810
1811                         //
1812                         // From any class S to any class-type T, provided S is a base class of T
1813                         //
1814                         if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true))
1815                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1816
1817                         //
1818                         // From any interface-type S to to any class type T, provided T is not
1819                         // sealed, or provided T implements S.
1820                         //
1821                         if (source_type.Kind == MemberKind.Interface) {
1822                                 if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) {
1823                                         if (source == null)
1824                                                 return EmptyExpression.Null;
1825
1826                                         //
1827                                         // Unboxing conversion from any interface-type to any non-nullable-value-type that
1828                                         // implements the interface-type
1829                                         //
1830                                         return target_is_value_type ? new UnboxCast (source, target_type) : (Expression) new ClassCast (source, target_type);
1831                                 }
1832
1833                                 //
1834                                 // From System.Collections.Generic.IList<T> and its base interfaces to a one-dimensional
1835                                 // array type S[], provided there is an implicit or explicit reference conversion from S to T.
1836                                 //
1837                                 var target_array = target_type as ArrayContainer;
1838                                 if (target_array != null && IList_To_Array (source_type, target_array))
1839                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1840
1841                                 return null;
1842                         }
1843
1844                         var source_array = source_type as ArrayContainer;
1845                         if (source_array != null) {
1846                                 var target_array = target_type as ArrayContainer;
1847                                 if (target_array != null) {
1848                                         //
1849                                         // From System.Array to any array-type
1850                                         //
1851                                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array)
1852                                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1853
1854                                         //
1855                                         // From an array type S with an element type Se to an array type T with an
1856                                         // element type Te provided all the following are true:
1857                                         //     * S and T differe only in element type, in other words, S and T
1858                                         //       have the same number of dimensions.
1859                                         //     * Both Se and Te are reference types
1860                                         //     * An explicit reference conversions exist from Se to Te
1861                                         //
1862                                         if (source_array.Rank == target_array.Rank) {
1863
1864                                                 source_type = source_array.Element;
1865                                                 if (!TypeSpec.IsReferenceType (source_type))
1866                                                         return null;
1867
1868                                                 var target_element = target_array.Element;
1869                                                 if (!TypeSpec.IsReferenceType (target_element))
1870                                                         return null;
1871
1872                                                 if (ExplicitReferenceConversionExists (source_type, target_element))
1873                                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1874                                                         
1875                                                 return null;
1876                                         }
1877                                 }
1878
1879                                 //
1880                                 // From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, 
1881                                 // provided that there is an explicit reference conversion from S to T
1882                                 //
1883                                 if (ArrayToIList (source_array, target_type, true))
1884                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1885
1886                                 return null;
1887                         }
1888
1889                         //
1890                         // From any class type S to any interface T, provides S is not sealed
1891                         // and provided S does not implement T.
1892                         //
1893                         if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type, true)) {
1894                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1895                         }
1896
1897                         //
1898                         // From System delegate to any delegate-type
1899                         //
1900                         if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && target_type.IsDelegate)
1901                                 return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1902
1903                         //
1904                         // From variant generic delegate to same variant generic delegate type
1905                         //
1906                         if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) {
1907                                 var tparams = source_type.MemberDefinition.TypeParameters;
1908                                 var targs_src = source_type.TypeArguments;
1909                                 var targs_dst = target_type.TypeArguments;
1910                                 int i;
1911                                 for (i = 0; i < tparams.Length; ++i) {
1912                                         //
1913                                         // If TP is invariant, types have to be identical
1914                                         //
1915                                         if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i]))
1916                                                 continue;
1917
1918                                         if (tparams[i].Variance == Variance.Covariant) {
1919                                                 //
1920                                                 //If TP is covariant, an implicit or explicit identity or reference conversion is required
1921                                                 //
1922                                                 if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1923                                                         continue;
1924
1925                                                 if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
1926                                                         continue;
1927
1928                                         } else if (tparams[i].Variance == Variance.Contravariant) {
1929                                                 //
1930                                                 //If TP is contravariant, both are either identical or reference types
1931                                                 //
1932                                                 if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i]))
1933                                                         continue;
1934                                         }
1935
1936                                         break;
1937                                 }
1938
1939                                 if (i == tparams.Length)
1940                                         return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1941                         }
1942
1943                         return null;
1944                 }
1945
1946                 /// <summary>
1947                 ///   Performs an explicit conversion of the expression `expr' whose
1948                 ///   type is expr.Type to `target_type'.
1949                 /// </summary>
1950                 static public Expression ExplicitConversionCore (ResolveContext ec, Expression expr,
1951                                                                  TypeSpec target_type, Location loc)
1952                 {
1953                         TypeSpec expr_type = expr.Type;
1954
1955                         // Explicit conversion includes implicit conversion and it used for enum underlying types too
1956                         Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true);
1957                         if (ne != null)
1958                                 return ne;
1959
1960                         if (expr_type.IsEnum) {
1961                                 TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1962                                 Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type));
1963                                 if (underlying.Type == real_target)
1964                                         ne = underlying;
1965
1966                                 if (ne == null)
1967                                         ne = ImplicitNumericConversion (underlying, real_target);
1968
1969                                 if (ne == null)
1970                                         ne = ExplicitNumericConversion (ec, underlying, real_target);
1971
1972                                 //
1973                                 // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
1974                                 //
1975                                 if (ne == null && (real_target.BuiltinType == BuiltinTypeSpec.Type.IntPtr || real_target.BuiltinType == BuiltinTypeSpec.Type.UIntPtr))
1976                                         ne = ExplicitUserConversion (ec, underlying, real_target, loc);
1977
1978                                 return ne != null ? EmptyCast.Create (ne, target_type) : null;
1979                         }
1980
1981                         if (target_type.IsEnum) {
1982                                 //
1983                                 // System.Enum can be unboxed to any enum-type
1984                                 //
1985                                 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Enum)
1986                                         return new UnboxCast (expr, target_type);
1987
1988                                 TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
1989
1990                                 if (expr_type == real_target)
1991                                         return EmptyCast.Create (expr, target_type);
1992
1993                                 ne = ImplicitNumericConversion (expr, real_target);
1994                                 if (ne != null)
1995                                         return EmptyCast.Create (ne, target_type);
1996
1997                                 ne = ExplicitNumericConversion (ec, expr, real_target);
1998                                 if (ne != null)
1999                                         return EmptyCast.Create (ne, target_type);
2000
2001                                 //
2002                                 // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
2003                                 //
2004                                 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.IntPtr || expr_type.BuiltinType == BuiltinTypeSpec.Type.UIntPtr) {
2005                                         ne = ExplicitUserConversion (ec, expr, real_target, loc);
2006                                         if (ne != null)
2007                                                 return ExplicitConversionCore (ec, ne, target_type, loc);
2008                                 }
2009                         } else {
2010                                 ne = ExplicitNumericConversion (ec, expr, target_type);
2011                                 if (ne != null)
2012                                         return ne;
2013                         }
2014
2015                         //
2016                         // Skip the ExplicitReferenceConversion because we can not convert
2017                         // from Null to a ValueType, and ExplicitReference wont check against
2018                         // null literal explicitly
2019                         //
2020                         if (expr_type != InternalType.NullLiteral) {
2021                                 ne = ExplicitReferenceConversion (expr, expr_type, target_type);
2022                                 if (ne != null)
2023                                         return ne;
2024                         }
2025
2026                         if (ec.IsUnsafe){
2027                                 ne = ExplicitUnsafe (expr, target_type);
2028                                 if (ne != null)
2029                                         return ne;
2030                         }
2031                         
2032                         return null;
2033                 }
2034
2035                 public static Expression ExplicitUnsafe (Expression expr, TypeSpec target_type)
2036                 {
2037                         TypeSpec expr_type = expr.Type;
2038
2039                         if (target_type.IsPointer){
2040                                 if (expr_type.IsPointer)
2041                                         return EmptyCast.Create (expr, target_type);
2042
2043                                 switch (expr_type.BuiltinType) {
2044                                 case BuiltinTypeSpec.Type.SByte:
2045                                 case BuiltinTypeSpec.Type.Short:
2046                                 case BuiltinTypeSpec.Type.Int:
2047                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
2048
2049                                 case BuiltinTypeSpec.Type.UShort:
2050                                 case BuiltinTypeSpec.Type.UInt:
2051                                 case BuiltinTypeSpec.Type.Byte:
2052                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2053
2054                                 case BuiltinTypeSpec.Type.Long:
2055                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I);
2056
2057                                 case BuiltinTypeSpec.Type.ULong:
2058                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I);
2059                                 }
2060                         }
2061
2062                         if (expr_type.IsPointer){
2063                                 switch (target_type.BuiltinType) {
2064                                 case BuiltinTypeSpec.Type.SByte:
2065                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
2066                                 case BuiltinTypeSpec.Type.Byte:
2067                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
2068                                 case BuiltinTypeSpec.Type.Short:
2069                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
2070                                 case BuiltinTypeSpec.Type.UShort:
2071                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
2072                                 case BuiltinTypeSpec.Type.Int:
2073                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
2074                                 case BuiltinTypeSpec.Type.UInt:
2075                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
2076                                 case BuiltinTypeSpec.Type.Long:
2077                                         return new ConvCast (expr, target_type, ConvCast.Mode.I_I8);
2078                                 case BuiltinTypeSpec.Type.ULong:
2079                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
2080                                 }
2081                         }
2082                         return null;
2083                 }
2084
2085                 /// <summary>
2086                 ///   Same as ExplicitConversion, only it doesn't include user defined conversions
2087                 /// </summary>
2088                 static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr,
2089                                                                      TypeSpec target_type, Location l)
2090                 {
2091                         int errors = ec.Report.Errors;
2092                         Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
2093                         if (ec.Report.Errors > errors)
2094                                 return null;
2095
2096                         if (ne != null)
2097                                 return ne;
2098
2099                         ne = ExplicitNumericConversion (ec, expr, target_type);
2100                         if (ne != null)
2101                                 return ne;
2102
2103                         ne = ExplicitReferenceConversion (expr, expr.Type, target_type);
2104                         if (ne != null)
2105                                 return ne;
2106
2107                         if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void)
2108                                 return EmptyCast.Create (expr, target_type);
2109
2110                         expr.Error_ValueCannotBeConverted (ec, target_type, true);
2111                         return null;
2112                 }
2113
2114                 /// <summary>
2115                 ///   Performs an explicit conversion of the expression `expr' whose
2116                 ///   type is expr.Type to `target_type'.
2117                 /// </summary>
2118                 static public Expression ExplicitConversion (ResolveContext ec, Expression expr,
2119                         TypeSpec target_type, Location loc)
2120                 {
2121                         Expression e = ExplicitConversionCore (ec, expr, target_type, loc);
2122                         if (e != null) {
2123                                 //
2124                                 // Don't eliminate explicit precission casts
2125                                 //
2126                                 if (e == expr) {
2127                                         if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float)
2128                                                 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
2129                                         
2130                                         if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
2131                                                 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
2132                                 }
2133                                         
2134                                 return e;
2135                         }
2136
2137                         TypeSpec expr_type = expr.Type;
2138                         if (target_type.IsNullableType) {
2139                                 TypeSpec target;
2140
2141                                 if (expr_type.IsNullableType) {
2142                                         target = Nullable.NullableInfo.GetUnderlyingType (target_type);
2143                                         Expression unwrap = Nullable.Unwrap.Create (expr);
2144                                         e = ExplicitConversion (ec, unwrap, target, expr.Location);
2145                                         if (e == null)
2146                                                 return null;
2147
2148                                         return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec);
2149                                 }
2150                                 if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2151                                         return new UnboxCast (expr, target_type);
2152                                 }
2153
2154                                 target = TypeManager.GetTypeArguments (target_type) [0];
2155                                 e = ExplicitConversionCore (ec, expr, target, loc);
2156                                 if (e != null)
2157                                         return Nullable.Wrap.Create (e, target_type);
2158                         } else if (expr_type.IsNullableType) {
2159                                 e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
2160                                 if (e != null)
2161                                         return e;
2162
2163                                 e = Nullable.Unwrap.Create (expr, false);                       
2164                                 e = ExplicitConversionCore (ec, e, target_type, loc);
2165                                 if (e != null)
2166                                         return EmptyCast.Create (e, target_type);
2167                         }
2168                         
2169                         e = ExplicitUserConversion (ec, expr, target_type, loc);
2170                         if (e != null)
2171                                 return e;                       
2172
2173                         expr.Error_ValueCannotBeConverted (ec, target_type, true);
2174                         return null;
2175                 }
2176         }
2177 }