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