Beispiel #1
0
 void UnpackNestedType(StringBuilder builder, IReturnType returnType)
 {
     if (returnType.IsArrayReturnType)
     {
         ArrayReturnType art = returnType.CastToArrayReturnType();
         builder.Append('(');
         UnpackNestedType(builder, art.ArrayElementType);
         if (art.ArrayDimensions > 1)
         {
             builder.Append(',');
             builder.Append(art.ArrayDimensions);
         }
         builder.Append(')');
     }
     else if (returnType.IsConstructedReturnType)
     {
         ConstructedReturnType crt = returnType.CastToConstructedReturnType();
         UnpackNestedType(builder, crt.UnboundType);
         builder.Append("[of ");
         for (int i = 0; i < crt.TypeArguments.Count; ++i)
         {
             if (i > 0)
             {
                 builder.Append(", ");
             }
             builder.Append(Convert(crt.TypeArguments[i]));
         }
         builder.Append(']');
     }
     else
     {
         string fullName = returnType.FullyQualifiedName;
         if (fullName != null && typeConversionTable.ContainsKey(fullName))
         {
             builder.Append(typeConversionTable[fullName].ToString());
         }
         else
         {
             if (UseFullyQualifiedTypeNames)
             {
                 builder.Append(fullName);
             }
             else
             {
                 builder.Append(returnType.Name);
             }
         }
     }
 }
Beispiel #2
0
        public override bool Equals(object o)
        {
            IReturnType rt = o as IReturnType;

            if (rt == null || !rt.IsArrayReturnType)
            {
                return(false);
            }
            ArrayReturnType art = rt.CastToArrayReturnType();

            if (art.ArrayDimensions != dimensions)
            {
                return(false);
            }
            return(elementType.Equals(art.ArrayElementType));
        }
Beispiel #3
0
        public virtual ArrayReturnType CastToArrayReturnType()
        {
            IReturnType     baseType = BaseType;
            ArrayReturnType temp;

            if (baseType != null && TryEnter())
            {
                temp = baseType.CastToArrayReturnType();
            }
            else
            {
                throw new InvalidCastException("Cannot cast " + ToString() + " to expected type.");
            }
            _busy = false;
            return(temp);
        }
Beispiel #4
0
			/// <summary>
			/// Gets whether this type parameter occurs in the specified return type.
			/// </summary>
			public bool OccursIn(IReturnType rt)
			{
				ArrayReturnType art = rt.CastToArrayReturnType();
				if (art != null) {
					return OccursIn(art.ArrayElementType);
				}
				ConstructedReturnType crt = rt.CastToConstructedReturnType();
				if (crt != null) {
					return crt.TypeArguments.Any(ta => OccursIn(ta));
				}
				GenericReturnType grt = rt.CastToGenericReturnType();
				if (grt != null) {
					return this.TypeParameter.Equals(grt.TypeParameter);
				}
				return false;
			}
		bool CheckReturnType(IReturnType t)
		{
			if (t.IsGenericReturnType) {
				return t.CastToGenericReturnType().TypeParameter.Method == null;
			} else if (t.IsArrayReturnType) {
				return CheckReturnType(t.CastToArrayReturnType().ArrayElementType);
			} else if (t.IsConstructedReturnType) {
				foreach (IReturnType para in t.CastToConstructedReturnType().TypeArguments) {
					if (para != null) {
						if (CheckReturnType(para)) return true;
					}
				}
				return false;
			} else {
				return false;
			}
		}
        static bool AreTypesDifferent(IReturnType oldType, CodeTypeReference newType)
        {
            IClass oldClass = oldType.GetUnderlyingClass();

            if (oldClass == null)
            {
                // ignore type changes to untyped VB fields
                return(false);
            }
            if (newType.BaseType == "System.Void")
            {
                // field types get replaced with System.Void if the type cannot be resolved
                // (e.g. generic fields in the Boo designer which aren't converted to CodeDom)
                // we'll ignore such type changes (fields should never have the type void)
                return(false);
            }

            ArrayReturnType oldArray = oldType.IsArrayReturnType ? oldType.CastToArrayReturnType() : null;

            if (oldArray == null ^ newType.ArrayRank < 1)
            {
                return(true);
            }

            if (oldArray == null)
            {
                if (oldClass.DotNetName != newType.BaseType)
                {
                    return(true);
                }
            }
            else
            {
                if (oldArray.ArrayDimensions != newType.ArrayRank)
                {
                    return(true);
                }
                if (AreTypesDifferent(oldArray.ArrayElementType, newType.ArrayElementType))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #7
0
        /// <summary>
        /// Make exact inference from U for V.
        /// </summary>
        void MakeExactInference(IReturnType U, IReturnType V)
        {
            Log(" MakeExactInference from " + U + " for " + V);
            if (U == null || V == null)
            {
                return;
            }

            // If V is one of the unfixed Xi then U is added to the set of bounds for Xi.
            TP tp = GetTPForType(V);

            if (tp != null && tp.Fixed == false)
            {
                Log(" Add bound '" + U.DotNetName + "' to " + tp);
                tp.Bounds.Add(U);
                return;
            }
            // Otherwise if U is an array type Ue[…] and V is an array type Ve[…] of the same rank
            // then an exact inference from Ue to Ve is made
            ArrayReturnType arrU = U.CastToArrayReturnType();
            ArrayReturnType arrV = V.CastToArrayReturnType();

            if (arrU != null && arrV != null && arrU.ArrayDimensions == arrV.ArrayDimensions)
            {
                MakeExactInference(arrU.ArrayElementType, arrV.ArrayElementType);
                return;
            }
            // Otherwise if V is a constructed type C<V1…Vk> and U is a constructed
            // type C<U1…Uk> then an exact inference is made from each Ui to the corresponding Vi.
            ConstructedReturnType CU = U.CastToConstructedReturnType();
            ConstructedReturnType CV = V.CastToConstructedReturnType();

            if (CU != null && CV != null &&
                object.Equals(CU.UnboundType, CV.UnboundType) &&
                CU.TypeArgumentCount == CV.TypeArgumentCount &&
                CU.TypeArguments.Count == CU.TypeArgumentCount &&
                CV.TypeArguments.Count == CV.TypeArgumentCount)
            {
                for (int i = 0; i < CU.TypeArgumentCount; i++)
                {
                    MakeExactInference(CU.TypeArguments[i], CV.TypeArguments[i]);
                }
                return;
            }
        }
        TypeResolveResult CreateTypeResolveResult(IReturnType resolvedType)
        {
            if (resolvedType == null)
            {
                return(null);
            }
            else
            {
                IReturnType rt = resolvedType;
                while (rt != null && rt.IsArrayReturnType)
                {
                    rt = rt.CastToArrayReturnType().ArrayElementType;
                }
                IClass resolvedClass = rt != null?rt.GetUnderlyingClass() : null;

                return(new TypeResolveResult(resolver.CallingClass, resolver.CallingMember, resolvedType, resolvedClass));
            }
        }
Beispiel #9
0
 public static IReturnType TranslateType(IReturnType input, IList <IReturnType> typeParameters, bool convertForMethod)
 {
     if (input == null || typeParameters == null || typeParameters.Count == 0)
     {
         return(input);                // nothing to do when there are no type parameters specified
     }
     if (input.IsGenericReturnType)
     {
         GenericReturnType rt = input.CastToGenericReturnType();
         if (convertForMethod ? (rt.TypeParameter.Method != null) : (rt.TypeParameter.Method == null))
         {
             if (rt.TypeParameter.Index < typeParameters.Count)
             {
                 IReturnType newType = typeParameters[rt.TypeParameter.Index];
                 if (newType != null)
                 {
                     return(newType);
                 }
             }
         }
     }
     else if (input.IsArrayReturnType)
     {
         ArrayReturnType arInput = input.CastToArrayReturnType();
         IReturnType     e       = arInput.ArrayElementType;
         IReturnType     t       = TranslateType(e, typeParameters, convertForMethod);
         if (e != t && t != null)
         {
             return(new ArrayReturnType(arInput.ProjectContent, t, arInput.ArrayDimensions));
         }
     }
     else if (input.IsConstructedReturnType)
     {
         ConstructedReturnType cinput = input.CastToConstructedReturnType();
         List <IReturnType>    para   = new List <IReturnType>(cinput.TypeArguments.Count);
         foreach (IReturnType argument in cinput.TypeArguments)
         {
             para.Add(TranslateType(argument, typeParameters, convertForMethod));
         }
         return(new ConstructedReturnType(cinput.UnboundType, para));
     }
     return(input);
 }
Beispiel #10
0
            /// <summary>
            /// Gets whether this type parameter occurs in the specified return type.
            /// </summary>
            public bool OccursIn(IReturnType rt)
            {
                ArrayReturnType art = rt.CastToArrayReturnType();

                if (art != null)
                {
                    return(OccursIn(art.ArrayElementType));
                }
                ConstructedReturnType crt = rt.CastToConstructedReturnType();

                if (crt != null)
                {
                    return(crt.TypeArguments.Any(ta => OccursIn(ta)));
                }
                GenericReturnType grt = rt.CastToGenericReturnType();

                if (grt != null)
                {
                    return(this.TypeParameter.Equals(grt.TypeParameter));
                }
                return(false);
            }
Beispiel #11
0
 void AddExternalType(IReturnType rt, List <ClassNameTypeCountPair> externalTypes, int classCount)
 {
     if (rt.IsDefaultReturnType)
     {
         ClassNameTypeCountPair pair = new ClassNameTypeCountPair(rt);
         if (!classIndices.ContainsKey(pair))
         {
             classIndices.Add(pair, externalTypes.Count + classCount);
             externalTypes.Add(pair);
         }
     }
     else if (rt.IsGenericReturnType)
     {
         // ignore
     }
     else if (rt.IsArrayReturnType)
     {
         AddExternalType(rt.CastToArrayReturnType().ArrayElementType, externalTypes, classCount);
     }
     else if (rt.IsConstructedReturnType)
     {
         AddExternalType(rt.CastToConstructedReturnType().UnboundType, externalTypes, classCount);
         foreach (IReturnType typeArgument in rt.CastToConstructedReturnType().TypeArguments)
         {
             AddExternalType(typeArgument, externalTypes, classCount);
         }
     }
     else if (rt.IsDecoratingReturnType <PointerReturnType>())
     {
         AddExternalType(rt.CastToDecoratingReturnType <PointerReturnType>().BaseType, externalTypes, classCount);
     }
     else
     {
         LoggingService.Warn("Unknown return type: " + rt.ToString());
     }
 }
        static bool IsApplicable(IList <IParameter> parameters,
                                 IReturnType[] arguments,
                                 bool allowAdditionalArguments,
                                 out int score,
                                 out bool expanded)
        {
            // see ECMA-334, § 14.4.2.1
            // TODO: recognize ref/out (needs info about passing mode for arguments, you have to introduce RefReturnType)

            expanded = false;
            score    = 0;
            if (parameters.Count == 0)
            {
                return(arguments.Length == 0);
            }
            if (!allowAdditionalArguments && parameters.Count > arguments.Length + 1)
            {
                return(false);
            }
            int lastParameter = parameters.Count - 1;

            // check all arguments except the last
            bool ok = true;

            for (int i = 0; i < Math.Min(lastParameter, arguments.Length); i++)
            {
                if (IsApplicable(arguments[i], parameters[i].ReturnType))
                {
                    score++;
                }
                else
                {
                    ok = false;
                }
            }
            if (!ok)
            {
                return(false);
            }
            if (parameters.Count == arguments.Length)
            {
                // try if method is applicable in normal form by checking last argument
                if (IsApplicable(arguments[lastParameter], parameters[lastParameter].ReturnType))
                {
                    return(true);
                }
            }
            // method is not applicable in normal form, try expanded form:
            // - last parameter must be params array
            if (!parameters[lastParameter].IsParams)
            {
                return(false);
            }
            expanded = true;
            score++;

            // - all additional parameters must be applicable to the unpacked array
            IReturnType rt = parameters[lastParameter].ReturnType;

            if (rt == null || !rt.IsArrayReturnType)
            {
                return(false);
            }
            for (int i = lastParameter; i < arguments.Length; i++)
            {
                if (IsApplicable(arguments[i], rt.CastToArrayReturnType().ArrayElementType))
                {
                    score++;
                }
                else
                {
                    ok = false;
                }
            }
            return(ok);
        }
        /// <summary>
        /// Infers type arguments specified by passing expectedArgument as parameter where passedArgument
        /// was expected. The resulting type arguments are written to outputArray.
        /// Returns false when expectedArgument and passedArgument are incompatible, otherwise true
        /// is returned (true is used both for successful inferring and other kind of errors).
        /// </summary>
        /// <remarks>
        /// The C# spec (§ 25.6.4) has a bug: it says that type inference works if the passedArgument is IEnumerable{T}
        /// and the expectedArgument is an array; passedArgument and expectedArgument must be swapped here.
        /// </remarks>
        public static bool InferTypeArgument(IReturnType expectedArgument, IReturnType passedArgument, IReturnType[] outputArray)
        {
            if (expectedArgument == null)
            {
                return(true);
            }
            if (passedArgument == null || passedArgument == NullReturnType.Instance)
            {
                return(true);
            }

            if (passedArgument.IsArrayReturnType)
            {
                IReturnType passedArrayElementType = passedArgument.CastToArrayReturnType().ArrayElementType;
                if (expectedArgument.IsArrayReturnType && expectedArgument.CastToArrayReturnType().ArrayDimensions == passedArgument.CastToArrayReturnType().ArrayDimensions)
                {
                    return(InferTypeArgument(expectedArgument.CastToArrayReturnType().ArrayElementType, passedArrayElementType, outputArray));
                }
                else if (expectedArgument.IsConstructedReturnType)
                {
                    switch (expectedArgument.FullyQualifiedName)
                    {
                    case "System.Collections.Generic.IList":
                    case "System.Collections.Generic.ICollection":
                    case "System.Collections.Generic.IEnumerable":
                        return(InferTypeArgument(expectedArgument.CastToConstructedReturnType().TypeArguments[0], passedArrayElementType, outputArray));
                    }
                }
                // If P is an array type, and A is not an array type of the same rank,
                // or an instantiation of IList<>, ICollection<>, or IEnumerable<>, then
                // type inference fails for the generic method.
                return(false);
            }
            if (expectedArgument.IsGenericReturnType)
            {
                GenericReturnType methodTP = expectedArgument.CastToGenericReturnType();
                if (methodTP.TypeParameter.Method != null)
                {
                    if (methodTP.TypeParameter.Index < outputArray.Length)
                    {
                        outputArray[methodTP.TypeParameter.Index] = passedArgument;
                    }
                    return(true);
                }
            }
            if (expectedArgument.IsConstructedReturnType)
            {
                // The spec for this case is quite complex.
                // For our purposes, we can simplify enourmously:
                if (!passedArgument.IsConstructedReturnType)
                {
                    return(false);
                }

                IList <IReturnType> expectedTA = expectedArgument.CastToConstructedReturnType().TypeArguments;
                IList <IReturnType> passedTA   = passedArgument.CastToConstructedReturnType().TypeArguments;

                int count = Math.Min(expectedTA.Count, passedTA.Count);
                for (int i = 0; i < count; i++)
                {
                    InferTypeArgument(expectedTA[i], passedTA[i], outputArray);
                }
            }
            return(true);
        }
		static int GetMoreSpecific(IReturnType r, IReturnType s)
		{
			if (r == null && s == null) return 0;
			if (r == null) return 2;
			if (s == null) return 1;
			if (r.IsGenericReturnType && !(s.IsGenericReturnType))
				return 2;
			if (s.IsGenericReturnType && !(r.IsGenericReturnType))
				return 1;
			if (r.IsArrayReturnType && s.IsArrayReturnType)
				return GetMoreSpecific(r.CastToArrayReturnType().ArrayElementType, s.CastToArrayReturnType().ArrayElementType);
			if (r.IsConstructedReturnType && s.IsConstructedReturnType)
				return GetMoreSpecific(r.CastToConstructedReturnType().TypeArguments, s.CastToConstructedReturnType().TypeArguments);
			return 0;
		}
Beispiel #15
0
		/// <summary>
		/// Make exact inference from U for V.
		/// </summary>
		void MakeExactInference(IReturnType U, IReturnType V)
		{
			Log(" MakeExactInference from " + U + " for " + V);
			if (U == null || V == null)
				return;
			
			// If V is one of the unfixed Xi then U is added to the set of bounds for Xi.
			TP tp = GetTPForType(V);
			if (tp != null && tp.Fixed == false) {
				Log(" Add bound '" + U.DotNetName + "' to " + tp);
				tp.Bounds.Add(U);
				return;
			}
			// Otherwise if U is an array type Ue[…] and V is an array type Ve[…] of the same rank
			// then an exact inference from Ue to Ve is made
			ArrayReturnType arrU = U.CastToArrayReturnType();
			ArrayReturnType arrV = V.CastToArrayReturnType();
			if (arrU != null && arrV != null && arrU.ArrayDimensions == arrV.ArrayDimensions) {
				MakeExactInference(arrU.ArrayElementType, arrV.ArrayElementType);
				return;
			}
			// Otherwise if V is a constructed type C<V1…Vk> and U is a constructed
			// type C<U1…Uk> then an exact inference is made from each Ui to the corresponding Vi.
			ConstructedReturnType CU = U.CastToConstructedReturnType();
			ConstructedReturnType CV = V.CastToConstructedReturnType();
			if (CU != null && CV != null
			    && object.Equals(CU.UnboundType, CV.UnboundType)
			    && CU.TypeArgumentCount == CV.TypeArgumentCount
			    && CU.TypeArguments.Count == CU.TypeArgumentCount
			    && CV.TypeArguments.Count == CV.TypeArgumentCount)
			{
				for (int i = 0; i < CU.TypeArgumentCount; i++) {
					MakeExactInference(CU.TypeArguments[i], CV.TypeArguments[i]);
				}
				return;
			}
		}
Beispiel #16
0
		static IReturnType GetElementType(IReturnType potentialArrayType)
		{
			if (potentialArrayType == null)
				return null;
			ArrayReturnType result;
			while ((result = potentialArrayType.CastToArrayReturnType()) != null) {
				potentialArrayType = result.ArrayElementType;
			}
			return potentialArrayType;
		}
			void AddExternalType(IReturnType rt, List<ClassNameTypeCountPair> externalTypes, int classCount)
			{
				if (rt.IsDefaultReturnType) {
					ClassNameTypeCountPair pair = new ClassNameTypeCountPair(rt);
					if (!classIndices.ContainsKey(pair)) {
						classIndices.Add(pair, externalTypes.Count + classCount);
						externalTypes.Add(pair);
					}
				} else if (rt.IsGenericReturnType) {
					// ignore
				} else if (rt.IsArrayReturnType) {
					AddExternalType(rt.CastToArrayReturnType().ArrayElementType, externalTypes, classCount);
				} else if (rt.IsConstructedReturnType) {
					AddExternalType(rt.CastToConstructedReturnType().UnboundType, externalTypes, classCount);
					foreach (IReturnType typeArgument in rt.CastToConstructedReturnType().TypeArguments) {
						AddExternalType(typeArgument, externalTypes, classCount);
					}
				} else if (rt.IsDecoratingReturnType<PointerReturnType>()) {
					AddExternalType(rt.CastToDecoratingReturnType<PointerReturnType>().BaseType, externalTypes, classCount);
				} else {
					LoggingService.Warn("Unknown return type: " + rt.ToString());
				}
			}
		public static IReturnType TranslateType(IReturnType input, IList<IReturnType> typeParameters, bool convertForMethod)
		{
			if (typeParameters == null || typeParameters.Count == 0) {
				return input; // nothing to do when there are no type parameters specified
			}
			if (input.IsGenericReturnType) {
				GenericReturnType rt = input.CastToGenericReturnType();
				if (convertForMethod ? (rt.TypeParameter.Method != null) : (rt.TypeParameter.Method == null)) {
					if (rt.TypeParameter.Index < typeParameters.Count) {
						IReturnType newType = typeParameters[rt.TypeParameter.Index];
						if (newType != null) {
							return newType;
						}
					}
				}
			} else if (input.IsArrayReturnType) {
				ArrayReturnType arInput = input.CastToArrayReturnType();
				IReturnType e = arInput.ArrayElementType;
				IReturnType t = TranslateType(e, typeParameters, convertForMethod);
				if (e != t && t != null)
					return new ArrayReturnType(arInput.ProjectContent, t, arInput.ArrayDimensions);
			} else if (input.IsConstructedReturnType) {
				ConstructedReturnType cinput = input.CastToConstructedReturnType();
				List<IReturnType> para = new List<IReturnType>(cinput.TypeArguments.Count);
				foreach (IReturnType argument in cinput.TypeArguments) {
					para.Add(TranslateType(argument, typeParameters, convertForMethod));
				}
				return new ConstructedReturnType(cinput.UnboundType, para);
			}
			return input;
		}
        /// <summary>
        /// Gets all types the specified type inherits from (all classes and interfaces).
        /// Unlike the class inheritance tree, this method takes care of type arguments and calculates the type
        /// arguments that are passed to base classes.
        /// </summary>
        public static IEnumerable <IReturnType> GetTypeInheritanceTree(IReturnType typeToListInheritanceTreeFor)
        {
            if (typeToListInheritanceTreeFor == null)
            {
                throw new ArgumentNullException("typeToListInheritanceTreeFor");
            }

            lock (getTypeInheritanceTreeCache) {
                IEnumerable <IReturnType> result;
                if (getTypeInheritanceTreeCache.TryGetValue(typeToListInheritanceTreeFor, out result))
                {
                    return(result);
                }
            }

            IClass classToListInheritanceTreeFor = typeToListInheritanceTreeFor.GetUnderlyingClass();

            if (classToListInheritanceTreeFor == null)
            {
                return new IReturnType[] { typeToListInheritanceTreeFor }
            }
            ;

            if (typeToListInheritanceTreeFor.IsArrayReturnType)
            {
                IReturnType elementType = typeToListInheritanceTreeFor.CastToArrayReturnType().ArrayElementType;

                List <IReturnType> resultList = new List <IReturnType>();
                resultList.Add(typeToListInheritanceTreeFor);
                resultList.AddRange(GetTypeInheritanceTree(
                                        new ConstructedReturnType(
                                            classToListInheritanceTreeFor.ProjectContent.GetClass("System.Collections.Generic.IList", 1).DefaultReturnType,
                                            new IReturnType[] { elementType }
                                            )
                                        ));
                resultList.Add(classToListInheritanceTreeFor.ProjectContent.GetClass("System.Collections.IList", 0).DefaultReturnType);
                resultList.Add(classToListInheritanceTreeFor.ProjectContent.GetClass("System.Collections.ICollection", 0).DefaultReturnType);
                // non-generic IEnumerable is already added by generic IEnumerable
                return(resultList);
            }

            HashSet <IReturnType> visitedSet   = new HashSet <IReturnType>();
            List <IReturnType>    visitedList  = new List <IReturnType>();
            Queue <IReturnType>   typesToVisit = new Queue <IReturnType>();
            bool enqueuedLastBaseType          = false;

            IReturnType currentType  = typeToListInheritanceTreeFor;
            IClass      currentClass = classToListInheritanceTreeFor;
            IReturnType nextType;

            do
            {
                if (currentClass != null)
                {
                    if (visitedSet.Add(currentType))
                    {
                        visitedList.Add(currentType);
                        foreach (IReturnType type in currentClass.BaseTypes)
                        {
                            typesToVisit.Enqueue(TranslateIfRequired(currentType, type));
                        }
                    }
                }
                if (typesToVisit.Count > 0)
                {
                    nextType = typesToVisit.Dequeue();
                }
                else
                {
                    nextType             = enqueuedLastBaseType ? null : DefaultClass.GetBaseTypeByClassType(classToListInheritanceTreeFor);
                    enqueuedLastBaseType = true;
                }
                if (nextType != null)
                {
                    currentType  = nextType;
                    currentClass = nextType.GetUnderlyingClass();
                }
            } while (nextType != null);
            lock (getTypeInheritanceTreeCache) {
                if (getTypeInheritanceTreeCache.Count == 0)
                {
                    DomCache.RegisterForClear(ClearGetTypeInheritanceTreeCache);
                }
                getTypeInheritanceTreeCache[typeToListInheritanceTreeFor] = visitedList;
            }
            return(visitedList);
        }
        /// <summary>
        /// Tests if an implicit conversion exists from "from" to "to".
        /// Conversions from concrete types to generic types are only allowed when the generic type belongs to the
        /// method "allowGenericTargetsOnThisMethod".
        /// </summary>
        static bool ConversionExistsInternal(IReturnType from, IReturnType to, IMethod allowGenericTargetsOnThisMethod)
        {
            // ECMA-334, § 13.1 Implicit conversions

            // Identity conversion:
            if (from == to)
            {
                return(true);
            }
            if (from == null || to == null)
            {
                return(false);
            }
            if (from.Equals(to))
            {
                return(true);
            }

            bool fromIsDefault = from.IsDefaultReturnType;
            bool toIsDefault   = to.IsDefaultReturnType;

            if (fromIsDefault && toIsDefault)
            {
                // Implicit numeric conversions:
                int f = GetPrimitiveType(from);
                int t = GetPrimitiveType(to);
                if (f == SByte && (t == Short || t == Int || t == Long || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Byte && (t == Short || t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Short && (t == Int || t == Long || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == UShort && (t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Int && (t == Long || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == UInt && (t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if ((f == Long || f == ULong) && (t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Char && (t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Float && t == Double)
                {
                    return(true);
                }
            }
            // Implicit reference conversions:

            if (toIsDefault && to.FullyQualifiedName == "System.Object")
            {
                return(true);                // from any type to object
            }
            if (from == NullReturnType.Instance)
            {
                IClass toClass = to.GetUnderlyingClass();
                if (toClass != null)
                {
                    switch (toClass.ClassType)
                    {
                    case ClassType.Class:
                    case ClassType.Delegate:
                    case ClassType.Interface:
                        return(true);

                    case ClassType.Struct:
                        return(toClass.FullyQualifiedName == "System.Nullable");
                    }
                }
                return(false);
            }

            if ((toIsDefault || to.IsConstructedReturnType || to.IsGenericReturnType) &&
                (fromIsDefault || from.IsArrayReturnType || from.IsConstructedReturnType))
            {
                foreach (IReturnType baseTypeOfFrom in GetTypeInheritanceTree(from))
                {
                    if (IsConstructedConversionToGenericReturnType(baseTypeOfFrom, to, allowGenericTargetsOnThisMethod))
                    {
                        return(true);
                    }
                }
            }

            if (from.IsArrayReturnType && to.IsArrayReturnType)
            {
                ArrayReturnType fromArt = from.CastToArrayReturnType();
                ArrayReturnType toArt   = to.CastToArrayReturnType();
                // from array to other array type
                if (fromArt.ArrayDimensions == toArt.ArrayDimensions)
                {
                    return(ConversionExistsInternal(fromArt.ArrayElementType, toArt.ArrayElementType, allowGenericTargetsOnThisMethod));
                }
            }

            if (from.IsDecoratingReturnType <AnonymousMethodReturnType>() && (toIsDefault || to.IsConstructedReturnType))
            {
                AnonymousMethodReturnType amrt = from.CastToDecoratingReturnType <AnonymousMethodReturnType>();
                IMethod method = CSharp.TypeInference.GetDelegateOrExpressionTreeSignature(to, amrt.CanBeConvertedToExpressionTree);
                if (method != null)
                {
                    if (amrt.HasParameterList)
                    {
                        if (amrt.MethodParameters.Count != method.Parameters.Count)
                        {
                            return(false);
                        }
                        for (int i = 0; i < amrt.MethodParameters.Count; i++)
                        {
                            if (amrt.MethodParameters[i].ReturnType != null)
                            {
                                if (!object.Equals(amrt.MethodParameters[i].ReturnType,
                                                   method.Parameters[i].ReturnType))
                                {
                                    return(false);
                                }
                            }
                        }
                    }
                    IReturnType rt = amrt.ResolveReturnType(method.Parameters.Select(p => p.ReturnType).ToArray());
                    return(ConversionExistsInternal(rt, method.ReturnType, allowGenericTargetsOnThisMethod));
                }
            }

            return(false);
        }
		/// <summary>
		/// Checks if an implicit conversion exists from <paramref name="from"/> to <paramref name="to"/>.
		/// </summary>
		public static bool ConversionExists(IReturnType from, IReturnType to)
		{
			// ECMA-334, § 13.1 Implicit conversions
			
			// Identity conversion:
			if (from == to) return true;
			if (from == null || to == null) return false;
			if (from.Equals(to)) {
				return true;
			}
			
			bool fromIsDefault = from.IsDefaultReturnType;
			bool toIsDefault = to.IsDefaultReturnType;
			
			if (fromIsDefault && toIsDefault) {
				// Implicit numeric conversions:
				int f = GetPrimitiveType(from);
				int t = GetPrimitiveType(to);
				if (f == SByte && (t == Short || t == Int || t == Long || t == Float || t == Double || t == Decimal))
					return true;
				if (f == Byte && (t == Short || t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
					return true;
				if (f == Short && (t == Int || t == Long || t == Float || t == Double || t == Decimal))
					return true;
				if (f == UShort && (t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
					return true;
				if (f == Int && (t == Long || t == Float || t == Double || t == Decimal))
					return true;
				if (f == UInt && (t == Long || t == ULong || t == Float || t == Double || t == Decimal))
					return true;
				if ((f == Long || f == ULong) && (t == Float || t == Double || t == Decimal))
					return true;
				if (f == Char && (t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
					return true;
				if (f == Float && t == Double)
					return true;
			}
			// Implicit reference conversions:
			
			if (toIsDefault && to.FullyQualifiedName == "System.Object") {
				return true; // from any type to object
			}
			if (toIsDefault && (fromIsDefault || from.IsArrayReturnType)) {
				IClass c1 = from.GetUnderlyingClass();
				IClass c2 = to.GetUnderlyingClass();
				if (c1 != null && c1.IsTypeInInheritanceTree(c2)) {
					return true;
				}
			}
			if (from.IsArrayReturnType && to.IsArrayReturnType) {
				ArrayReturnType fromArt = from.CastToArrayReturnType();
				ArrayReturnType toArt   = to.CastToArrayReturnType();
				// from array to other array type
				if (fromArt.ArrayDimensions == toArt.ArrayDimensions) {
					return ConversionExists(fromArt.ArrayElementType, toArt.ArrayElementType);
				}
			}
			
			if (from.IsConstructedReturnType && to.IsConstructedReturnType) {
				if (from.FullyQualifiedName == to.FullyQualifiedName) {
					IList<IReturnType> fromTypeArguments = from.CastToConstructedReturnType().TypeArguments;
					IList<IReturnType> toTypeArguments = to.CastToConstructedReturnType().TypeArguments;
					if (fromTypeArguments.Count == toTypeArguments.Count) {
						for (int i = 0; i < fromTypeArguments.Count; i++) {
							if (fromTypeArguments[i] == toTypeArguments[i])
								continue;
							if (object.Equals(fromTypeArguments[i], toTypeArguments[i]))
								continue;
							if (!(toTypeArguments[i].IsGenericReturnType))
								return false;
						}
						return true;
					}
				}
			}
			
			return false;
		}
		/// <summary>
		/// Infers type arguments specified by passing expectedArgument as parameter where passedArgument
		/// was expected. The resulting type arguments are written to outputArray.
		/// Returns false when expectedArgument and passedArgument are incompatible, otherwise true
		/// is returned (true is used both for successful inferring and other kind of errors).
		/// </summary>
		public static bool InferTypeArgument(IReturnType expectedArgument, IReturnType passedArgument, IReturnType[] outputArray)
		{
			if (expectedArgument == null) return true;
			if (passedArgument == null) return true; // TODO: NullTypeReference
			if (expectedArgument.IsArrayReturnType) {
				IReturnType expectedArrayElementType = expectedArgument.CastToArrayReturnType().ArrayElementType;
				if (passedArgument.IsArrayReturnType && expectedArgument.CastToArrayReturnType().ArrayDimensions == passedArgument.CastToArrayReturnType().ArrayDimensions) {
					return InferTypeArgument(expectedArrayElementType, passedArgument.CastToArrayReturnType().ArrayElementType, outputArray);
				} else if (passedArgument.IsConstructedReturnType) {
					switch (passedArgument.FullyQualifiedName) {
						case "System.Collections.Generic.IList":
						case "System.Collections.Generic.ICollection":
						case "System.Collections.Generic.IEnumerable":
							return InferTypeArgument(expectedArrayElementType, passedArgument.CastToConstructedReturnType().TypeArguments[0], outputArray);
					}
				}
				// If P is an array type, and A is not an array type of the same rank,
				// or an instantiation of IList<>, ICollection<>, or IEnumerable<>, then
				// type inference fails for the generic method.
				return false;
			}
			if (expectedArgument.IsGenericReturnType) {
				GenericReturnType methodTP = expectedArgument.CastToGenericReturnType();
				if (methodTP.TypeParameter.Method != null) {
					if (methodTP.TypeParameter.Index < outputArray.Length) {
						outputArray[methodTP.TypeParameter.Index] = passedArgument;
					}
					return true;
				}
			}
			if (expectedArgument.IsConstructedReturnType) {
				// The spec for this case is quite complex.
				// For our purposes, we can simplify enourmously:
				if (!passedArgument.IsConstructedReturnType) return false;
				
				IList<IReturnType> expectedTA = expectedArgument.CastToConstructedReturnType().TypeArguments;
				IList<IReturnType> passedTA   = passedArgument.CastToConstructedReturnType().TypeArguments;
				
				int count = Math.Min(expectedTA.Count, passedTA.Count);
				for (int i = 0; i < count; i++) {
					InferTypeArgument(expectedTA[i], passedTA[i], outputArray);
				}
			}
			return true;
		}
Beispiel #23
0
		void UnpackNestedType(StringBuilder builder, IReturnType returnType)
		{
			if (returnType.IsArrayReturnType) {
				ArrayReturnType art = returnType.CastToArrayReturnType();
				builder.Append('(');
				UnpackNestedType(builder, art.ArrayElementType);
				if (art.ArrayDimensions > 1) {
					builder.Append(',');
					builder.Append(art.ArrayDimensions);
				}
				builder.Append(')');
			} else if (returnType.IsConstructedReturnType) {
				ConstructedReturnType crt = returnType.CastToConstructedReturnType();
				UnpackNestedType(builder, crt.UnboundType);
				builder.Append("[of ");
				for (int i = 0; i < crt.TypeArguments.Count; ++i) {
					if (i > 0) builder.Append(", ");
					builder.Append(Convert(crt.TypeArguments[i]));
				}
				builder.Append(']');
			} else {
				string fullName = returnType.FullyQualifiedName;
				if (fullName != null && typeConversionTable.ContainsKey(fullName)) {
					builder.Append(typeConversionTable[fullName].ToString());
				} else {
					if (UseFullyQualifiedTypeNames) {
						builder.Append(fullName);
					} else {
						builder.Append(returnType.Name);
					}
				}
			}
		}
        /// <summary>
        /// Checks if an implicit conversion exists from <paramref name="from"/> to <paramref name="to"/>.
        /// </summary>
        public static bool ConversionExists(IReturnType from, IReturnType to)
        {
            // ECMA-334, § 13.1 Implicit conversions

            // Identity conversion:
            if (from == to)
            {
                return(true);
            }
            if (from == null || to == null)
            {
                return(false);
            }
            if (from.Equals(to))
            {
                return(true);
            }

            bool fromIsDefault = from.IsDefaultReturnType;
            bool toIsDefault   = to.IsDefaultReturnType;

            if (fromIsDefault && toIsDefault)
            {
                // Implicit numeric conversions:
                int f = GetPrimitiveType(from);
                int t = GetPrimitiveType(to);
                if (f == SByte && (t == Short || t == Int || t == Long || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Byte && (t == Short || t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Short && (t == Int || t == Long || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == UShort && (t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Int && (t == Long || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == UInt && (t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if ((f == Long || f == ULong) && (t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Char && (t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Float && t == Double)
                {
                    return(true);
                }
            }
            // Implicit reference conversions:

            if (toIsDefault && to.FullyQualifiedName == "System.Object")
            {
                return(true);                // from any type to object
            }
            if (toIsDefault && (fromIsDefault || from.IsArrayReturnType))
            {
                IClass c1 = from.GetUnderlyingClass();
                IClass c2 = to.GetUnderlyingClass();
                if (c1 != null && c1.IsTypeInInheritanceTree(c2))
                {
                    return(true);
                }
            }
            if (from.IsArrayReturnType && to.IsArrayReturnType)
            {
                ArrayReturnType fromArt = from.CastToArrayReturnType();
                ArrayReturnType toArt   = to.CastToArrayReturnType();
                // from array to other array type
                if (fromArt.ArrayDimensions == toArt.ArrayDimensions)
                {
                    return(ConversionExists(fromArt.ArrayElementType, toArt.ArrayElementType));
                }
            }

            if (from.IsConstructedReturnType && to.IsConstructedReturnType)
            {
                if (from.FullyQualifiedName == to.FullyQualifiedName)
                {
                    IList <IReturnType> fromTypeArguments = from.CastToConstructedReturnType().TypeArguments;
                    IList <IReturnType> toTypeArguments   = to.CastToConstructedReturnType().TypeArguments;
                    if (fromTypeArguments.Count == toTypeArguments.Count)
                    {
                        for (int i = 0; i < fromTypeArguments.Count; i++)
                        {
                            if (fromTypeArguments[i] == toTypeArguments[i])
                            {
                                continue;
                            }
                            if (object.Equals(fromTypeArguments[i], toTypeArguments[i]))
                            {
                                continue;
                            }
                            if (!(toTypeArguments[i].IsGenericReturnType))
                            {
                                return(false);
                            }
                        }
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #25
0
        /// <summary>
        /// Make lower bound inference from U for V.
        /// </summary>
        void MakeLowerBoundInference(IReturnType U, IReturnType V)
        {
            Log(" MakeLowerBoundInference from " + U + " for " + V);
            if (U == null || V == null)
            {
                return;
            }

            // If V is one of the unfixed Xi then U is added to the set of bounds for Xi.
            TP tp = GetTPForType(V);

            if (tp != null && tp.Fixed == false)
            {
                Log("  Add bound '" + U.DotNetName + "' to " + tp);
                tp.Bounds.Add(U);
                return;
            }
            // Otherwise if U is an array type Ue[…] and V is either an array type Ve[…]of the
            // same rank, or if U is a one­dimensional array type Ue[]and V is one of
            // IEnumerable<Ve>, ICollection<Ve> or IList<Ve> then
            ArrayReturnType       arrU = U.CastToArrayReturnType();
            ArrayReturnType       arrV = V.CastToArrayReturnType();
            ConstructedReturnType CV   = V.CastToConstructedReturnType();

            if (arrU != null &&
                (arrV != null && arrU.ArrayDimensions == arrV.ArrayDimensions ||
                 (arrU.ArrayDimensions == 1 && IsIEnumerableCollectionOrList(CV))))
            {
                IReturnType Ue = arrU.ArrayElementType;
                IReturnType Ve = arrV != null ? arrV.ArrayElementType : CV.TypeArguments[0];
                // If Ue is known to be a reference type then a lower­bound inference from Ue to Ve is made
                if (IsReferenceType(Ue) ?? false)
                {
                    MakeLowerBoundInference(Ue, Ve);
                }
                else
                {
                    // Otherwise an exact inference from Ue to Ve is made
                    MakeExactInference(Ue, Ve);
                }
                return;
            }
            // Otherwise if V is a constructed type C<V1…Vk> and there is a unique set of
            // types U1…Uk such that a standard implicit conversion exists from U to C<U1…Uk>
            // then an exact inference is made from each Ui for the corresponding Vi.
            if (CV != null)
            {
                foreach (IReturnType U2 in MemberLookupHelper.GetTypeInheritanceTree(U))
                {
                    ConstructedReturnType CU2 = U2.CastToConstructedReturnType();
                    if (CU2 != null &&
                        object.Equals(CU2.UnboundType, CV.UnboundType) &&
                        CU2.TypeArgumentCount == CV.TypeArgumentCount &&
                        CU2.TypeArguments.Count == CU2.TypeArgumentCount &&                     // unfortunately these might not be the same...
                        CV.TypeArguments.Count == CV.TypeArgumentCount)
                    {
                        for (int i = 0; i < CU2.TypeArgumentCount; i++)
                        {
                            MakeExactInference(CU2.TypeArguments[i], CV.TypeArguments[i]);
                        }
                        return;
                    }
                }
            }
        }
        public static TypeReference ConvertType(IReturnType returnType, ClassFinder context)
        {
            if (returnType == null)
            {
                return(TypeReference.Null);
            }
            if (returnType is NullReturnType)
            {
                return(TypeReference.Null);
            }

            ArrayReturnType arrayReturnType = returnType.CastToArrayReturnType();

            if (arrayReturnType != null)
            {
                TypeReference typeRef = ConvertType(arrayReturnType.ArrayElementType, context);
                int[]         rank    = typeRef.RankSpecifier ?? new int[0];
                Array.Resize(ref rank, rank.Length + 1);
                rank[rank.Length - 1] = arrayReturnType.ArrayDimensions - 1;
                typeRef.RankSpecifier = rank;
                return(typeRef);
            }
            PointerReturnType pointerReturnType = returnType.CastToDecoratingReturnType <PointerReturnType>();

            if (pointerReturnType != null)
            {
                TypeReference typeRef = ConvertType(pointerReturnType.BaseType, context);
                typeRef.PointerNestingLevel++;
                return(typeRef);
            }

            IList <IReturnType> typeArguments = EmptyList <IReturnType> .Instance;

            if (returnType.IsConstructedReturnType)
            {
                typeArguments = returnType.CastToConstructedReturnType().TypeArguments;
            }
            IClass c = returnType.GetUnderlyingClass();

            if (c != null)
            {
                return(CreateTypeReference(c, typeArguments, context));
            }
            else
            {
                TypeReference typeRef;
                if (IsPrimitiveType(returnType))
                {
                    typeRef = new TypeReference(returnType.FullyQualifiedName, true);
                }
                else if (context != null && CanUseShortTypeName(returnType, context))
                {
                    typeRef = new TypeReference(returnType.Name);
                }
                else
                {
                    string fullName = returnType.FullyQualifiedName;
                    if (string.IsNullOrEmpty(fullName))
                    {
                        fullName = returnType.Name;
                    }
                    typeRef = new TypeReference(fullName);
                }
                foreach (IReturnType typeArgument in typeArguments)
                {
                    typeRef.GenericTypes.Add(ConvertType(typeArgument, context));
                }
                return(typeRef);
            }
        }
			void WriteType(IReturnType rt)
			{
				if (rt == null) {
					writer.Write(NullRTReferenceCode);
					return;
				}
				if (rt.IsDefaultReturnType) {
					string name = rt.FullyQualifiedName;
					if (name == "System.Void") {
						writer.Write(VoidRTCode);
					} else {
						writer.Write(classIndices[new ClassNameTypeCountPair(rt)]);
					}
				} else if (rt.IsGenericReturnType) {
					GenericReturnType grt = rt.CastToGenericReturnType();
					if (grt.TypeParameter.Method != null) {
						writer.Write(MethodGenericRTCode);
					} else {
						writer.Write(TypeGenericRTCode);
					}
					writer.Write(grt.TypeParameter.Index);
				} else if (rt.IsArrayReturnType) {
					writer.Write(ArrayRTCode);
					writer.Write(rt.CastToArrayReturnType().ArrayDimensions);
					WriteType(rt.CastToArrayReturnType().ArrayElementType);
				} else if (rt.IsConstructedReturnType) {
					ConstructedReturnType crt = rt.CastToConstructedReturnType();
					writer.Write(ConstructedRTCode);
					WriteType(crt.UnboundType);
					writer.Write((byte)crt.TypeArguments.Count);
					foreach (IReturnType typeArgument in crt.TypeArguments) {
						WriteType(typeArgument);
					}
				} else if (rt.IsDecoratingReturnType<PointerReturnType>()) {
					writer.Write(PointerRTCode);
					WriteType(rt.CastToDecoratingReturnType<PointerReturnType>().BaseType);
				} else {
					writer.Write(NullRTReferenceCode);
					LoggingService.Warn("Unknown return type: " + rt.ToString());
				}
			}
Beispiel #28
0
 void WriteType(IReturnType rt)
 {
     if (rt == null)
     {
         writer.Write(NullRTReferenceCode);
         return;
     }
     if (rt.IsDefaultReturnType)
     {
         string name = rt.FullyQualifiedName;
         if (name == "System.Void")
         {
             writer.Write(VoidRTCode);
         }
         else if (name == "dynamic")
         {
             writer.Write(DynamicRTCode);
         }
         else
         {
             writer.Write(classIndices[new ClassNameTypeCountPair(rt)]);
         }
     }
     else if (rt.IsGenericReturnType)
     {
         GenericReturnType grt = rt.CastToGenericReturnType();
         if (grt.TypeParameter.Method != null)
         {
             writer.Write(MethodGenericRTCode);
         }
         else
         {
             writer.Write(TypeGenericRTCode);
         }
         writer.Write(grt.TypeParameter.Index);
     }
     else if (rt.IsArrayReturnType)
     {
         writer.Write(ArrayRTCode);
         writer.Write(rt.CastToArrayReturnType().ArrayDimensions);
         WriteType(rt.CastToArrayReturnType().ArrayElementType);
     }
     else if (rt.IsConstructedReturnType)
     {
         ConstructedReturnType crt = rt.CastToConstructedReturnType();
         writer.Write(ConstructedRTCode);
         WriteType(crt.UnboundType);
         writer.Write((byte)crt.TypeArguments.Count);
         foreach (IReturnType typeArgument in crt.TypeArguments)
         {
             WriteType(typeArgument);
         }
     }
     else if (rt.IsDecoratingReturnType <PointerReturnType>())
     {
         writer.Write(PointerRTCode);
         WriteType(rt.CastToDecoratingReturnType <PointerReturnType>().BaseType);
     }
     else
     {
         writer.Write(NullRTReferenceCode);
         LoggingService.Warn("Unknown return type: " + rt.ToString());
     }
 }
		void UnpackNestedType(StringBuilder builder, IReturnType returnType)
		{
			if (returnType.IsArrayReturnType) {
				builder.Append('(');
				int dimensions = returnType.CastToArrayReturnType().ArrayDimensions;
				for (int i = 1; i < dimensions; ++i) {
					builder.Append(',');
				}
				builder.Append(')');
				UnpackNestedType(builder, returnType.CastToArrayReturnType().ArrayElementType);
			} else if (returnType.IsConstructedReturnType) {
				UnpackNestedType(builder, returnType.CastToConstructedReturnType().UnboundType);
				builder.Append("(Of ");
				IList<IReturnType> ta = returnType.CastToConstructedReturnType().TypeArguments;
				for (int i = 0; i < ta.Count; ++i) {
					if (i > 0) builder.Append(", ");
					builder.Append(Convert(ta[i]));
				}
				builder.Append(')');
			}
		}
		static bool AreTypesDifferent(IReturnType oldType, CodeTypeReference newType)
		{
			IClass oldClass = oldType.GetUnderlyingClass();
			if (oldClass == null) {
				// ignore type changes to untyped VB fields
				return false;
			}
			if (newType.BaseType == "System.Void") {
				// field types get replaced with System.Void if the type cannot be resolved
				// (e.g. generic fields in the Boo designer which aren't converted to CodeDom)
				// we'll ignore such type changes (fields should never have the type void)
				return false;
			}
			
			ArrayReturnType oldArray = oldType.IsArrayReturnType ? oldType.CastToArrayReturnType() : null;
			if (oldArray == null ^ newType.ArrayRank < 1)
			{
				return true;
			}
			
			if (oldArray == null) {
				
				if (oldClass.DotNetName != newType.BaseType) {
					return true;
				}
				
			} else {
				
				if (oldArray.ArrayDimensions != newType.ArrayRank) {
					return true;
				}
				if (AreTypesDifferent(oldArray.ArrayElementType, newType.ArrayElementType)) {
					return true;
				}
				
			}
			
			return false;
		}
Beispiel #31
0
		static void UnpackArrayType(StringBuilder builder, IReturnType returnType)
		{
			if (returnType.IsArrayReturnType) {
				builder.Append('[');
				int dimensions = returnType.CastToArrayReturnType().ArrayDimensions;
				for (int i = 1; i < dimensions; ++i) {
					builder.Append(',');
				}
				builder.Append(']');
				UnpackArrayType(builder, returnType.CastToArrayReturnType().ArrayElementType);
			}
		}
Beispiel #32
0
		/// <summary>
		/// Make lower bound inference from U for V.
		/// </summary>
		void MakeLowerBoundInference(IReturnType U, IReturnType V)
		{
			Log(" MakeLowerBoundInference from " + U + " for " + V);
			if (U == null || V == null)
				return;
			
			// If V is one of the unfixed Xi then U is added to the set of bounds for Xi.
			TP tp = GetTPForType(V);
			if (tp != null && tp.Fixed == false) {
				Log("  Add bound '" + U.DotNetName + "' to " + tp);
				tp.Bounds.Add(U);
				return;
			}
			// Otherwise if U is an array type Ue[…] and V is either an array type Ve[…]of the
			// same rank, or if U is a one­dimensional array type Ue[]and V is one of
			// IEnumerable<Ve>, ICollection<Ve> or IList<Ve> then
			ArrayReturnType arrU = U.CastToArrayReturnType();
			ArrayReturnType arrV = V.CastToArrayReturnType();
			ConstructedReturnType CV = V.CastToConstructedReturnType();
			if (arrU != null &&
			    (arrV != null && arrU.ArrayDimensions == arrV.ArrayDimensions
			     || (arrU.ArrayDimensions == 1 && IsIEnumerableCollectionOrList(CV))))
			{
				IReturnType Ue = arrU.ArrayElementType;
				IReturnType Ve = arrV != null ? arrV.ArrayElementType : CV.TypeArguments[0];
				// If Ue is known to be a reference type then a lower­bound inference from Ue to Ve is made
				if (IsReferenceType(Ue) ?? false) {
					MakeLowerBoundInference(Ue, Ve);
				} else {
					// Otherwise an exact inference from Ue to Ve is made
					MakeExactInference(Ue, Ve);
				}
				return;
			}
			// Otherwise if V is a constructed type C<V1…Vk> and there is a unique set of
			// types U1…Uk such that a standard implicit conversion exists from U to C<U1…Uk>
			// then an exact inference is made from each Ui for the corresponding Vi.
			if (CV != null) {
				foreach (IReturnType U2 in MemberLookupHelper.GetTypeInheritanceTree(U)) {
					ConstructedReturnType CU2 = U2.CastToConstructedReturnType();
					if (CU2 != null &&
					    object.Equals(CU2.UnboundType, CV.UnboundType) &&
					    CU2.TypeArgumentCount == CV.TypeArgumentCount
					    && CU2.TypeArguments.Count == CU2.TypeArgumentCount // unfortunately these might not be the same...
					    && CV.TypeArguments.Count == CV.TypeArgumentCount)
					{
						for (int i = 0; i < CU2.TypeArgumentCount; i++) {
							MakeExactInference(CU2.TypeArguments[i], CV.TypeArguments[i]);
						}
						return;
					}
				}
			}
		}