Пример #1
0
		//
		// From a one-dimensional array-type S[] to System.Collections.IList<T> and base
		// interfaces of this interface, provided there is an implicit reference conversion
		// from S to T.
		//
		static bool ArrayToIList (ArrayContainer array, TypeSpec list, bool isExplicit)
		{
			if (array.Rank != 1 || !list.IsGeneric)
				return false;

			var open_version = list.GetDefinition ();
			if ((open_version != TypeManager.generic_ilist_type) &&
				(open_version != TypeManager.generic_icollection_type) &&
				(open_version != TypeManager.generic_ienumerable_type))
				return false;

			var arg_type = list.TypeArguments[0];
			if (array.Element == arg_type)
				return true;

			if (isExplicit)
				return ExplicitReferenceConversionExists (array.Element, arg_type);

			if (MyEmptyExpr == null)
				MyEmptyExpr = new EmptyExpression (array.Element);
			else
				MyEmptyExpr.SetType (array.Element);

			return ImplicitReferenceConversionExists (MyEmptyExpr, arg_type);
		}
Пример #2
0
	public static bool IsNullableType (TypeSpec t)
	{
		return generic_nullable_type == t.GetDefinition ();
	}
Пример #3
0
	//
	// Checks whether `type' is a nested child of `parent'.
	//
	public static bool IsNestedChildOf (TypeSpec type, TypeSpec parent)
	{
		if (type == null)
			return false;

		type = type.GetDefinition (); // DropGenericTypeArguments (type);
		parent = parent.GetDefinition (); // DropGenericTypeArguments (parent);

		if (type == parent)
			return false;

		type = type.DeclaringType;
		while (type != null) {
			if (type.GetDefinition () == parent)
				return true;

			type = type.DeclaringType;
		}

		return false;
	}
Пример #4
0
		/// <summary>
		///  Same as ImplicitStandardConversionExists except that it also looks at
		///  implicit user defined conversions - needed for overload resolution
		/// </summary>
		public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type)
		{
			if (ImplicitStandardConversionExists (expr, target_type))
				return true;

			if (expr.Type == InternalType.AnonymousMethod) {
				if (!TypeManager.IsDelegateType (target_type) && target_type.GetDefinition () != TypeManager.expression_type)
					return false;

				AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
				return ame.ImplicitStandardConversionExists (ec, target_type);
			}
			
			if (expr.eclass == ExprClass.MethodGroup) {
				if (target_type.IsDelegate && RootContext.Version != LanguageVersion.ISO_1) {
					MethodGroupExpr mg = expr as MethodGroupExpr;
					if (mg != null)
						return DelegateCreation.ImplicitStandardConversionExists (ec, mg, target_type);
				}

				return false;
			}

			return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null;
		}
Пример #5
0
		public static TypeSpec GetUnderlyingType (TypeSpec t)
		{
			return ((EnumSpec) t.GetDefinition ()).UnderlyingType;
		}
Пример #6
0
		TypeSpec CompatibleChecks (ResolveContext ec, TypeSpec delegate_type)
		{
			if (delegate_type.IsDelegate)
				return delegate_type;

			if (delegate_type.IsGeneric && delegate_type.GetDefinition () == TypeManager.expression_type) {
				delegate_type = delegate_type.TypeArguments [0];
				if (delegate_type.IsDelegate)
					return delegate_type;

				ec.Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'",
					GetSignatureForError (), TypeManager.CSharpName (delegate_type));
				return null;
			}

			ec.Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'",
				      GetSignatureForError (), TypeManager.CSharpName (delegate_type));
			return null;
		}
Пример #7
0
		//
		// Infers type arguments based on explicit arguments
		//
		public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, TypeSpec delegate_type)
		{
			if (!HasExplicitParameters)
				return false;

			if (!delegate_type.IsDelegate) {
				if (delegate_type.GetDefinition () != TypeManager.expression_type)
					return false;

				delegate_type = TypeManager.GetTypeArguments (delegate_type) [0];
				if (!delegate_type.IsDelegate)
					return false;
			}
			
			AParametersCollection d_params = Delegate.GetParameters (ec.Compiler, delegate_type);
			if (d_params.Count != Parameters.Count)
				return false;

			for (int i = 0; i < Parameters.Count; ++i) {
				TypeSpec itype = d_params.Types [i];
				if (!TypeManager.IsGenericParameter (itype)) {
					if (!TypeManager.HasElementType (itype))
						continue;
					
					if (!TypeManager.IsGenericParameter (TypeManager.GetElementType (itype)))
					    continue;
				}
				type_inference.ExactInference (Parameters.Types [i], itype);
			}
			return true;
		}
Пример #8
0
		public bool CheckAccessLevel (TypeSpec check_type)
		{
// TODO: Use this instead
//			return PartialContainer.Definition.IsAccessible (check_type);

			TypeSpec tb = PartialContainer.Definition;
			check_type = check_type.GetDefinition ();

			var check_attr = check_type.Modifiers & Modifiers.AccessibilityMask;

			switch (check_attr){
			case Modifiers.PUBLIC:
				return true;

			case Modifiers.INTERNAL:
				return TypeManager.IsThisOrFriendAssembly (Assembly, check_type.Assembly);
				
			case Modifiers.PRIVATE:
				TypeSpec declaring = check_type.DeclaringType;
				return tb == declaring.GetDefinition () || TypeManager.IsNestedChildOf (tb, declaring);	

			case Modifiers.PROTECTED:
				//
				// Only accessible to methods in current type or any subtypes
				//
				return TypeManager.IsNestedFamilyAccessible (tb, check_type.DeclaringType);

			case Modifiers.PROTECTED | Modifiers.INTERNAL:
				if (TypeManager.IsThisOrFriendAssembly (Assembly, check_type.Assembly))
					return true;

				goto case Modifiers.PROTECTED;
			}

			throw new NotImplementedException (check_attr.ToString ());
		}
Пример #9
0
        //
        //  7.4.3.3  Better conversion from expression
        //  Returns :   1    if a->p is better,
        //              2    if a->q is better,
        //              0 if neither is better
        //
        static int BetterExpressionConversion(ResolveContext ec, Argument a, TypeSpec p, TypeSpec q)
        {
            TypeSpec argument_type = a.Type;
            if (argument_type == InternalType.AnonymousMethod && RootContext.Version > LanguageVersion.ISO_2) {
                //
                // Uwrap delegate from Expression<T>
                //
                if (p.GetDefinition () == TypeManager.expression_type) {
                    p = TypeManager.GetTypeArguments (p) [0];
                }
                if (q.GetDefinition () == TypeManager.expression_type) {
                    q = TypeManager.GetTypeArguments (q) [0];
                }

                p = Delegate.GetInvokeMethod (ec.Compiler, p).ReturnType;
                q = Delegate.GetInvokeMethod (ec.Compiler, q).ReturnType;
                if (p == TypeManager.void_type && q != TypeManager.void_type)
                    return 2;
                if (q == TypeManager.void_type && p != TypeManager.void_type)
                    return 1;
            } else {
                if (argument_type == p)
                    return 1;

                if (argument_type == q)
                    return 2;
            }

            return BetterTypeConversion (ec, p, q);
        }
Пример #10
0
		//
		// Lower-bound (false) or Upper-bound (true) inference based on inversed argument
		//
		int LowerBoundInference (TypeSpec u, TypeSpec v, bool inversed)
		{
			// If V is one of the unfixed type arguments
			int pos = IsUnfixed (v);
			if (pos != -1) {
				AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos);
				return 1;
			}			

			// If U is an array type
			var u_ac = u as ArrayContainer;
			if (u_ac != null) {
				var v_ac = v as ArrayContainer;
				if (v_ac != null) {
					if (u_ac.Rank != v_ac.Rank)
						return 0;

					if (TypeManager.IsValueType (u_ac.Element))
						return ExactInference (u_ac.Element, v_ac.Element);

					return LowerBoundInference (u_ac.Element, v_ac.Element, inversed);
				}

				if (u_ac.Rank != 1)
					return 0;

				if (TypeManager.IsGenericType (v)) {
					TypeSpec g_v = v.GetDefinition ();
					if (g_v != TypeManager.generic_ilist_type &&
						g_v != TypeManager.generic_icollection_type &&
						g_v != TypeManager.generic_ienumerable_type)
						return 0;

					var v_i = TypeManager.GetTypeArguments (v) [0];
					if (TypeManager.IsValueType (u_ac.Element))
						return ExactInference (u_ac.Element, v_i);

					return LowerBoundInference (u_ac.Element, v_i);
				}
			} else if (TypeManager.IsGenericType (v)) {
				//
				// if V is a constructed type C<V1..Vk> and there is a unique type C<U1..Uk>
				// such that U is identical to, inherits from (directly or indirectly),
				// or implements (directly or indirectly) C<U1..Uk>
				//
				var u_candidates = new List<TypeSpec> ();
				var open_v = v.MemberDefinition;

				for (TypeSpec t = u; t != null; t = t.BaseType) {
					if (open_v == t.MemberDefinition)
						u_candidates.Add (t);

					if (t.Interfaces != null) {
						foreach (var iface in t.Interfaces) {
							if (open_v == iface.MemberDefinition)
								u_candidates.Add (iface);
						}
					}
				}

				TypeSpec [] unique_candidate_targs = null;
				TypeSpec[] ga_v = TypeManager.GetTypeArguments (v);
				foreach (TypeSpec u_candidate in u_candidates) {
					//
					// The unique set of types U1..Uk means that if we have an interface I<T>,
					// class U : I<int>, I<long> then no type inference is made when inferring
					// type I<T> by applying type U because T could be int or long
					//
					if (unique_candidate_targs != null) {
						TypeSpec[] second_unique_candidate_targs = TypeManager.GetTypeArguments (u_candidate);
						if (TypeSpecComparer.Default.Equals (unique_candidate_targs, second_unique_candidate_targs)) {
							unique_candidate_targs = second_unique_candidate_targs;
							continue;
						}

						//
						// This should always cause type inference failure
						//
						failed = true;
						return 1;
					}

					unique_candidate_targs = TypeManager.GetTypeArguments (u_candidate);
				}

				if (unique_candidate_targs != null) {
					var ga_open_v = open_v.TypeParameters;
					int score = 0;
					for (int i = 0; i < unique_candidate_targs.Length; ++i) {
						Variance variance = ga_open_v [i].Variance;

						TypeSpec u_i = unique_candidate_targs [i];
						if (variance == Variance.None || TypeManager.IsValueType (u_i)) {
							if (ExactInference (u_i, ga_v [i]) == 0)
								++score;
						} else {
							bool upper_bound = (variance == Variance.Contravariant && !inversed) ||
								(variance == Variance.Covariant && inversed);

							if (LowerBoundInference (u_i, ga_v [i], upper_bound) == 0)
								++score;
						}
					}
					return score;
				}
			}

			return 0;
		}
Пример #11
0
		static bool HasDefaultConstructor (TypeSpec atype)
		{
			var tp = atype as TypeParameterSpec;
			if (tp != null) {
				return tp.HasSpecialConstructor || tp.HasSpecialStruct;
			}

			if (atype.IsStruct || atype.IsEnum)
				return true;

			if (atype.IsAbstract)
				return false;

			var tdef = atype.GetDefinition ();

			//
			// In some circumstances MemberCache is not yet populated and members
			// cannot be defined yet (recursive type new constraints)
			//
			// class A<T> where T : B<T>, new () {}
			// class B<T> where T : A<T>, new () {}
			//
			var tc = tdef.MemberDefinition as Class;
			if (tc != null) {
				if (tc.InstanceConstructors == null) {
					// Default ctor will be generated later
					return true;
				}

				foreach (var c in tc.InstanceConstructors) {
					if (c.ParameterInfo.IsEmpty) {
						if ((c.ModFlags & Modifiers.PUBLIC) != 0)
							return true;
					}
				}

				return false;
			}

			var found = MemberCache.FindMember (tdef,
				MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters),
				BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly);

			return found != null && (found.Modifiers & Modifiers.PUBLIC) != 0;
		}
Пример #12
0
		public GenericOpenTypeExpr (TypeSpec type, /*UnboundTypeArguments args,*/ Location loc)
		{
			this.type = type.GetDefinition ();
			this.loc = loc;
		}