Esempio n. 1
0
		public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
		{
			switch (target_type.BuiltinType) {
			//
			// From any non-nullable-value-type to the type object and dynamic
			//
			case BuiltinTypeSpec.Type.Object:
			case BuiltinTypeSpec.Type.Dynamic:
			//
			// From any non-nullable-value-type to the type System.ValueType
			//
			case BuiltinTypeSpec.Type.ValueType:
				//
				// No ned to check for nullable type as underlying type is always convertible
				//
				if (!TypeSpec.IsValueType (expr_type))
					return null;

				return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);

			case BuiltinTypeSpec.Type.Enum:
				//
				// From any enum-type to the type System.Enum.
				//
				if (expr_type.IsEnum)
					return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);

				break;
			}

			//
			// From a nullable-type to a reference type, if a boxing conversion exists from
			// the underlying type to the reference type
			//
			if (expr_type.IsNullableType) {
				if (!TypeSpec.IsReferenceType (target_type))
					return null;

				var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);

				// "cast" underlying type to target type to emit correct InvalidCastException when
				// underlying hierarchy changes without recompilation
				if (res != null && expr != null)
					res = new UnboxCast (res, target_type);

				return res;
			}

			//
			// A value type has a boxing conversion to an interface type I if it has a boxing conversion
			// to an interface or delegate type I0 and I0 is variance-convertible to I
			//
			if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) {
				return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
			}

			return null;
		}
Esempio n. 2
0
		/// <summary>
		///   Implements Explicit Reference conversions
		/// </summary>
		static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
		{
			//
			// From object to a generic parameter
			//
			if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type))
				return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);

			//
			// Explicit type parameter conversion.
			//
			if (source_type.Kind == MemberKind.TypeParameter)
				return ExplicitTypeParameterConversion (source, source_type, target_type);

			bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum;

			//
			// Unboxing conversion from System.ValueType to any non-nullable-value-type
			//
			if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type)
				return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);

			//
			// From object or dynamic to any reference type or value type (unboxing)
			//
			if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
				if (target_type.IsPointer)
					return null;

				return
					source == null ? EmptyExpression.Null :
					target_is_value_type ? new UnboxCast (source, target_type) :
					source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) :
					new ClassCast (source, target_type);
			}

			//
			// From any class S to any class-type T, provided S is a base class of T
			//
			if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true))
				return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

			//
			// From any interface-type S to to any class type T, provided T is not
			// sealed, or provided T implements S.
			//
			if (source_type.Kind == MemberKind.Interface) {
				if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) {
					if (source == null)
						return EmptyExpression.Null;

					//
					// Unboxing conversion from any interface-type to any non-nullable-value-type that
					// implements the interface-type
					//
					return target_is_value_type ? new UnboxCast (source, target_type) : (Expression) new ClassCast (source, target_type);
				}

				//
				// From System.Collections.Generic.IList<T> and its base interfaces to a one-dimensional
				// array type S[], provided there is an implicit or explicit reference conversion from S to T.
				//
				var target_array = target_type as ArrayContainer;
				if (target_array != null && IList_To_Array (source_type, target_array))
					return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

				return null;
			}

			var source_array = source_type as ArrayContainer;
			if (source_array != null) {
				var target_array = target_type as ArrayContainer;
				if (target_array != null) {
					//
					// From System.Array to any array-type
					//
					if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array)
						return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

					//
					// From an array type S with an element type Se to an array type T with an
					// element type Te provided all the following are true:
					//     * S and T differe only in element type, in other words, S and T
					//       have the same number of dimensions.
					//     * Both Se and Te are reference types
					//     * An explicit reference conversions exist from Se to Te
					//
					if (source_array.Rank == target_array.Rank) {

						source_type = source_array.Element;
						if (!TypeSpec.IsReferenceType (source_type))
							return null;

						var target_element = target_array.Element;
						if (!TypeSpec.IsReferenceType (target_element))
							return null;

						if (ExplicitReferenceConversionExists (source_type, target_element))
							return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
							
						return null;
					}
				}

				//
				// From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, 
				// provided that there is an explicit reference conversion from S to T
				//
				if (ArrayToIList (source_array, target_type, true))
					return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

				return null;
			}

			//
			// From any class type S to any interface T, provides S is not sealed
			// and provided S does not implement T.
			//
			if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type, true)) {
				return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
			}

			//
			// From System delegate to any delegate-type
			//
			if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && target_type.IsDelegate)
				return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

			//
			// From variant generic delegate to same variant generic delegate type
			//
			if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) {
				var tparams = source_type.MemberDefinition.TypeParameters;
				var targs_src = source_type.TypeArguments;
				var targs_dst = target_type.TypeArguments;
				int i;
				for (i = 0; i < tparams.Length; ++i) {
					//
					// If TP is invariant, types have to be identical
					//
					if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i]))
						continue;

					if (tparams[i].Variance == Variance.Covariant) {
						//
						//If TP is covariant, an implicit or explicit identity or reference conversion is required
						//
						if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
							continue;

						if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
							continue;

					} else if (tparams[i].Variance == Variance.Contravariant) {
						//
						//If TP is contravariant, both are either identical or reference types
						//
						if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i]))
							continue;
					}

					break;
				}

				if (i == tparams.Length)
					return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
			}

			return null;
		}
Esempio n. 3
0
		public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter)
		{
			// It's here only to speed things up
			if (target_type.IsStruct)
				return false;

			switch (expr_type.Kind) {
			case MemberKind.TypeParameter:
				return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null &&
					(!refOnlyTypeParameter || TypeSpec.IsReferenceType (expr_type));

			case MemberKind.Class:
				//
				// From any class-type to dynamic (+object to speed up common path)
				//
				if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
					return true;

				if (target_type.IsClass) {
					//
					// Identity conversion, including dynamic erasure
					//
					if (TypeSpecComparer.IsEqual (expr_type, target_type))
						return true;

					//
					// From any class-type S to any class-type T, provided S is derived from T
					//
					return TypeSpec.IsBaseClass (expr_type, target_type, true);
				}

				//
				// From any class-type S to any interface-type T, provided S implements T
				//
				if (target_type.IsInterface)
					return expr_type.ImplementsInterface (target_type, true);

				return false;

			case MemberKind.ArrayType:
				//
				// Identity array conversion
				//
				if (expr_type == target_type)
					return true;

				//
				// From any array-type to System.Array
				//
				switch (target_type.BuiltinType) {
				case BuiltinTypeSpec.Type.Array:
				case BuiltinTypeSpec.Type.Object:
				case BuiltinTypeSpec.Type.Dynamic:
					return true;
				}

				var expr_type_array = (ArrayContainer) expr_type;
				var target_type_array = target_type as ArrayContainer;

				//
				// From an array-type S to an array-type of type T
				//
				if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) {

					//
					// Both SE and TE are reference-types. TE check is defered
					// to ImplicitReferenceConversionExists
					//
					TypeSpec expr_element_type = expr_type_array.Element;
					if (!TypeSpec.IsReferenceType (expr_element_type))
						return false;

					//
					// An implicit reference conversion exists from SE to TE
					//
					return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element);
				}

				//
				// From any array-type to the interfaces it implements
				//
				if (target_type.IsInterface) {
					if (expr_type.ImplementsInterface (target_type, false))
						return true;

					// from an array-type of type T to IList<T>
					if (ArrayToIList (expr_type_array, target_type, false))
						return true;
				}

				return false;

			case MemberKind.Delegate:
				//
				// From any delegate-type to System.Delegate (and its base types)
				//
				switch (target_type.BuiltinType) {
				case BuiltinTypeSpec.Type.Delegate:
				case BuiltinTypeSpec.Type.MulticastDelegate:
				case BuiltinTypeSpec.Type.Object:
				case BuiltinTypeSpec.Type.Dynamic:
					return true;
				}

				//
				// Identity conversion, including dynamic erasure
				//
				if (TypeSpecComparer.IsEqual (expr_type, target_type))
					return true;

				//
				// From any delegate-type to the interfaces it implements
				// From any reference-type to an delegate type if is variance-convertible
				//
				return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type);

			case MemberKind.Interface:
				//
				// Identity conversion, including dynamic erasure
				//
				if (TypeSpecComparer.IsEqual (expr_type, target_type))
					return true;

				//
				// From any interface type S to interface-type T
				// From any reference-type to an interface if is variance-convertible
				//
				if (target_type.IsInterface)
					return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true);

				return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
			}

			//
			// from the null literal to any reference-type.
			//
			if (expr_type == InternalType.NullLiteral) {
				// Exlude internal compiler types
				if (target_type.Kind == MemberKind.InternalCompilerType)
					return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;

				return TypeSpec.IsReferenceType (target_type);
			}

			return false;
		}
Esempio n. 4
0
		//
		// Return container with awaiter definition. It never returns null
		// but all container member can be null for easier error reporting
		//
		public AwaiterDefinition GetAwaiter (TypeSpec type)
		{
			AwaiterDefinition awaiter;
			if (awaiters.TryGetValue (type, out awaiter))
				return awaiter;

			awaiter = new AwaiterDefinition ();

			//
			// Predefined: bool IsCompleted { get; } 
			//
			awaiter.IsCompleted = MemberCache.FindMember (type, MemberFilter.Property ("IsCompleted", Compiler.BuiltinTypes.Bool),
				BindingRestriction.InstanceOnly) as PropertySpec;

			//
			// Predefined: GetResult ()
			//
			// The method return type is also result type of await expression
			//
			awaiter.GetResult = MemberCache.FindMember (type, MemberFilter.Method ("GetResult", 0,
				ParametersCompiled.EmptyReadOnlyParameters, null),
				BindingRestriction.InstanceOnly) as MethodSpec;

			//
			// Predefined: INotifyCompletion.OnCompleted (System.Action)
			//
			var nc = PredefinedTypes.INotifyCompletion;
			awaiter.INotifyCompletion = !nc.Define () || type.ImplementsInterface (nc.TypeSpec, false);

			awaiters.Add (type, awaiter);
			return awaiter;
		}
Esempio n. 5
0
		public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
		{
			//
			// From any value-type to the type object.
			//
			if (target_type == TypeManager.object_type || target_type == InternalType.Dynamic) {
				//
				// A pointer type cannot be converted to object
				//
				if (expr_type.IsPointer)
					return null;

				if (!TypeManager.IsValueType (expr_type))
					return null;

				return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
			}
			
			//
			// From any value-type to the type System.ValueType.
			//
			if (target_type == TypeManager.value_type) {
				if (!TypeManager.IsValueType (expr_type))
					return null;

				return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
			}

			if (target_type == TypeManager.enum_type) {
				//
				// From any enum-type to the type System.Enum.
				//
				if (TypeManager.IsEnumType (expr_type))
					return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
			}

			//
			// From a nullable-type to a reference type, if a boxing conversion exists from
			// the underlying type to the reference type
			//
			if (TypeManager.IsNullableType (expr_type)) {
				if (!TypeManager.IsReferenceType (target_type))
					return null;

				var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);

				// "cast" underlying type to target type to emit correct InvalidCastException when
				// underlying hierarchy changes without recompilation
				if (res != null && expr != null)
					res = new UnboxCast (res, target_type);

				return res;
			}

			if (TypeSpec.IsBaseClass (expr_type, target_type, false)) {
				//
				// Don't box same type arguments
				//
				if (TypeManager.IsGenericParameter (expr_type) && expr_type != target_type)
					return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);

				return null;
			}

			// This code is kind of mirrored inside ImplicitStandardConversionExists
			// with the small distinction that we only probe there
			//
			// Always ensure that the code here and there is in sync

			// from any class-type S to any interface-type T.
			if (target_type.IsInterface) {
				if (expr_type.ImplementsInterface (target_type, true) &&
					(TypeManager.IsGenericParameter (expr_type) || TypeManager.IsValueType (expr_type))) {
					return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
				}
			}

			return null;
		}
Esempio n. 6
0
        public static bool ImplicitBoxingConversionExists(TypeSpec expr_type, TypeSpec target_type, out bool use_class_cast)
        {
            use_class_cast = false;

            //
            // From any value-type to the type object.
            //
            if (target_type == TypeManager.object_type || target_type == InternalType.Dynamic) {
                //
                // A pointer type cannot be converted to object
                //
                if (expr_type.IsPointer)
                    return false;

                return TypeManager.IsValueType (expr_type);
            }

            //
            // From any value-type to the type System.ValueType.
            //
            if (target_type == TypeManager.value_type)
                return TypeManager.IsValueType (expr_type);

            if (target_type == TypeManager.enum_type) {
                //
                // From any enum-type to the type System.Enum.
                //
                if (TypeManager.IsEnumType (expr_type))
                    return true;
            }

            //
            // From a nullable-type to a reference type, if a boxing conversion exists from
            // the underlying type to the reference type
            //
            if (TypeManager.IsNullableType (expr_type)) {
                if (!TypeManager.IsReferenceType (target_type))
                    return false;

                return ImplicitBoxingConversionExists (Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type, out use_class_cast);
            }

            if (TypeManager.IsSubclassOf (expr_type, target_type)) {
                //
                // Don't box same type arguments
                //
                if (TypeManager.IsGenericParameter (expr_type) && expr_type != target_type)
                    return true;

                return false;
            }

            // This code is kind of mirrored inside ImplicitStandardConversionExists
            // with the small distinction that we only probe there
            //
            // Always ensure that the code here and there is in sync

            // from any class-type S to any interface-type T.
            if (target_type.IsInterface) {
                if (expr_type.ImplementsInterface (target_type))
                    return TypeManager.IsGenericParameter (expr_type) ||
                        TypeManager.IsValueType (expr_type);
            }

            return false;
        }
Esempio n. 7
0
        /// <summary>
        ///   Implements Explicit Reference conversions
        /// </summary>
        static Expression ExplicitReferenceConversion(Expression source, TypeSpec source_type, TypeSpec target_type)
        {
            //
            // From object to a generic parameter
            //
            if (source_type == TypeManager.object_type && TypeManager.IsGenericParameter (target_type))
                return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);

            //
            // Explicit type parameter conversion.
            //
            if (TypeManager.IsGenericParameter (source_type))
                return ExplicitTypeParameterConversion (source, source_type, target_type);

            bool target_is_value_type = TypeManager.IsStruct (target_type) || TypeManager.IsEnumType (target_type);

            //
            // Unboxing conversion from System.ValueType to any non-nullable-value-type
            //
            if (source_type == TypeManager.value_type && target_is_value_type)
                return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);

            //
            // From object to any reference type or value type (unboxing)
            //
            if (source_type == TypeManager.object_type)
                return source == null ? EmptyExpression.Null :
                    target_is_value_type ? (Expression) new UnboxCast (source, target_type) : new ClassCast (source, target_type);

            //
            // From any class S to any class-type T, provided S is a base class of T
            //
            if (TypeManager.IsSubclassOf (target_type, source_type))
                return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

            //
            // From any interface-type S to to any class type T, provided T is not
            // sealed, or provided T implements S.
            //
            if (source_type.IsInterface) {
                if (!target_type.IsSealed || target_type.ImplementsInterface (source_type)) {
                    if (target_type.IsClass)
                        return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

                    //
                    // Unboxing conversion from any interface-type to any non-nullable-value-type that
                    // implements the interface-type
                    //
                    return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
                }

                //
                // From System.Collections.Generic.IList<T> and its base interfaces to a one-dimensional
                // array type S[], provided there is an implicit or explicit reference conversion from S to T.
                //
                var target_array = target_type as ArrayContainer;
                if (target_array != null && IList_To_Array (source_type, target_array))
                    return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

                return null;
            }

            var source_array = source_type as ArrayContainer;
            if (source_array != null) {
                var target_array = target_type as ArrayContainer;
                if (target_array != null) {
                    //
                    // From System.Array to any array-type
                    //
                    if (source_type == TypeManager.array_type)
                        return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

                    //
                    // From an array type S with an element type Se to an array type T with an
                    // element type Te provided all the following are true:
                    //     * S and T differe only in element type, in other words, S and T
                    //       have the same number of dimensions.
                    //     * Both Se and Te are reference types
                    //     * An explicit reference conversions exist from Se to Te
                    //
                    if (source_array.Rank == target_array.Rank) {

                        source_type = source_array.Element;
                        if (!TypeManager.IsReferenceType (source_type))
                            return null;

                        var target_element = target_array.Element;
                        if (!TypeManager.IsReferenceType (target_element))
                            return null;

                        if (ExplicitReferenceConversionExists (source_type, target_element))
                            return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

                        return null;
                    }
                }

                //
                // From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces,
                // provided that there is an explicit reference conversion from S to T
                //
                if (ArrayToIList (source_array, target_type, true))
                    return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

                return null;
            }

            //
            // From any class type S to any interface T, provides S is not sealed
            // and provided S does not implement T.
            //
            if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type)) {
                return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
            }

            //
            // From System delegate to any delegate-type
            //
            if (source_type == TypeManager.delegate_type && TypeManager.IsDelegateType (target_type))
                return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);

            return null;
        }
Esempio n. 8
0
		//
		// 6.1.6 Implicit reference conversions
		//
		public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type)
		{
			if (target_type.IsStruct)
				return false;

			// from the null type to any reference-type.
			if (expr_type == InternalType.NullLiteral)
				return true;

			if (expr_type.IsGenericParameter)
				return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null;

			// This code is kind of mirrored inside ImplicitStandardConversionExists
			// with the small distinction that we only probe there
			//
			// Always ensure that the code here and there is in sync

			// from any class-type S to any interface-type T.
			if (target_type.IsInterface) {
				if (expr_type.ImplementsInterface (target_type, true)){
					return !TypeManager.IsValueType (expr_type);
				}
			}

			//
			// Implicit reference conversions (no-boxing) to object or dynamic
			//
			if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
				switch (expr_type.Kind) {
				case MemberKind.Class:
				case MemberKind.Interface:
				case MemberKind.Delegate:
				case MemberKind.ArrayType:
					return true;
				}

				return expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
			}

			if (expr_type == target_type || TypeSpec.IsBaseClass (expr_type, target_type, true)) {
				if (TypeManager.IsGenericParameter (expr_type))
					return false;

				if (TypeManager.IsValueType (expr_type))
					return false;

				// Array type variance conversion
				//if (target_type.IsArray != expr_type.IsArray)
				//	return false;

				return true;
			}

			var expr_type_array = expr_type as ArrayContainer;
			if (expr_type_array != null) {
				var target_type_array = target_type as ArrayContainer;
				// from an array-type S to an array-type of type T
				if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) {

					//
					// Both SE and TE are reference-types
					//
					TypeSpec expr_element_type = expr_type_array.Element;
					if (!TypeManager.IsReferenceType (expr_element_type))
						return false;

					TypeSpec target_element_type = target_type_array.Element;
					if (!TypeManager.IsReferenceType (target_element_type))
						return false;

					//
					// An implicit reference conversion exists from SE to TE
					//
					return ImplicitReferenceConversionExists (expr_element_type, target_element_type);
				}

				// from an array-type to System.Array
				if (target_type.BuiltinType == BuiltinTypeSpec.Type.Array)
					return true;

				// from an array-type of type T to IList<T>
				if (ArrayToIList (expr_type_array, target_type, false))
					return true;

				return false;
			}

			if (TypeSpecComparer.IsEqual (expr_type, target_type))
				return true;

			if (TypeSpecComparer.Variant.IsEqual (expr_type, target_type))
				return true;

			// from any interface type S to interface-type T.
			if (expr_type.IsInterface && target_type.IsInterface) {
				return expr_type.ImplementsInterface (target_type, true);
			}

			// from any delegate type to System.Delegate
			if (target_type.BuiltinType == BuiltinTypeSpec.Type.Delegate &&
				(expr_type.BuiltinType == BuiltinTypeSpec.Type.Delegate || expr_type.IsDelegate))
				return true;

			return false;
		}
Esempio n. 9
0
        public override bool Resolve(BlockContext ec)
        {
            expr = expr.Resolve (ec);
            if (expr == null)
                return false;

            expr_type = expr.Type;

            if (!expr_type.ImplementsInterface (TypeManager.idisposable_type) &&
                Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) {
                if (expr_type != InternalType.Dynamic) {
                    Using.Error_IsNotConvertibleToIDisposable (ec, expr);
                    return false;
                }

                expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.idisposable_type, loc);
                expr_type = expr.Type;
            }

            local_copy = new TemporaryVariable (expr_type, loc);
            local_copy.Resolve (ec);

            ec.StartFlowBranching (this);

            bool ok = Statement.Resolve (ec);

            ec.EndFlowBranching ();

            ok &= base.Resolve (ec);

            if (TypeManager.void_dispose_void == null) {
                TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
                    TypeManager.idisposable_type, "Dispose", loc, TypeSpec.EmptyTypes);
            }

            return ok;
        }
Esempio n. 10
0
            public override bool Resolve(BlockContext ec)
            {
                enumerator_type = TypeManager.ienumerator_type;

                bool is_dynamic = expr.Type == InternalType.Dynamic;
                if (is_dynamic)
                    expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.ienumerable_type, loc);

                if (!ProbeCollectionType (ec, expr.Type)) {
                    Error_Enumerator (ec);
                    return false;
                }

                VarExpr ve = var_type as VarExpr;
                if (ve != null) {
                    // Infer implicitly typed local variable from foreach enumerable type
                    var_type = new TypeExpression (
                        is_dynamic ? InternalType.Dynamic : get_current.Type,
                        var_type.Location);
                }

                var_type = var_type.ResolveAsTypeTerminal (ec, false);
                if (var_type == null)
                    return false;

                enumerator = new TemporaryVariable (enumerator_type, loc);
                enumerator.Resolve (ec);

                init = new Invocation (get_enumerator, null);
                init = init.Resolve (ec);
                if (init == null)
                    return false;

                Expression move_next_expr;
                {
                    var mi = new List<MemberSpec> (1) { move_next };
                    MethodGroupExpr mg = new MethodGroupExpr (mi, var_type.Type, loc);
                    mg.InstanceExpression = enumerator;

                    move_next_expr = new Invocation (mg, null);
                }

                get_current.InstanceExpression = enumerator;

                Statement block = new CollectionForeachStatement (
                    var_type.Type, variable, get_current, statement, loc);

                loop = new While (new BooleanExpression (move_next_expr), block, loc);

                bool implements_idisposable = enumerator_type.ImplementsInterface (TypeManager.idisposable_type);
                if (implements_idisposable || !enumerator_type.IsSealed) {
                    wrapper = new DisposableWrapper (this, implements_idisposable);
                } else {
                    wrapper = new NonDisposableWrapper (this);
                }

                return wrapper.Resolve (ec);
            }