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