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