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