예제 #1
0
        public void ArrayToEnumerable()
        {
            ITypeParameter  tp             = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
            IType           stringType     = compilation.FindType(KnownTypeCode.String);
            ITypeDefinition enumerableType = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition();

            bool success;

            Assert.AreEqual(
                new [] { stringType },
                ti.InferTypeArguments(new [] { tp },
                                      new [] { new ResolveResult(new ArrayType(compilation, stringType)) },
                                      new [] { new ParameterizedType(enumerableType, new [] { tp }) },
                                      out success));
            Assert.IsTrue(success);
        }
예제 #2
0
        void RunTypeInference(Candidate candidate)
        {
            IMethod method = candidate.Member as IMethod;

            if (method == null || method.TypeParameters.Count == 0)
            {
                if (explicitlyGivenTypeArguments != null)
                {
                    // method does not expect type arguments, but was given some
                    candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments);
                }
                return;
            }
            // The method is generic:
            if (explicitlyGivenTypeArguments != null)
            {
                if (explicitlyGivenTypeArguments.Length == method.TypeParameters.Count)
                {
                    candidate.InferredTypes = explicitlyGivenTypeArguments;
                }
                else
                {
                    candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments);
                    // wrong number of type arguments given, so truncate the list or pad with UnknownType
                    candidate.InferredTypes = new IType[method.TypeParameters.Count];
                    for (int i = 0; i < candidate.InferredTypes.Length; i++)
                    {
                        if (i < explicitlyGivenTypeArguments.Length)
                        {
                            candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i];
                        }
                        else
                        {
                            candidate.InferredTypes[i] = SharedTypes.UnknownType;
                        }
                    }
                }
            }
            else
            {
                TypeInference ti = new TypeInference(context, conversions);
                bool          success;
                candidate.InferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, candidate.ParameterTypes, out success);
                if (!success)
                {
                    candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed);
                }
            }
            // Now substitute in the formal parameters:
            var substitution = new ConstraintValidatingSubstitution(candidate.InferredTypes, this);

            for (int i = 0; i < candidate.ParameterTypes.Length; i++)
            {
                candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution);
            }
            if (!substitution.ConstraintsValid)
            {
                candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint);
            }
        }
예제 #3
0
        public void ArrayToEnumerable()
        {
            ITypeParameter  tp             = new DefaultTypeParameter(EntityType.Method, 0, "T");
            IType           stringType     = KnownTypeReference.String.Resolve(ctx);
            ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable <>));

            bool success;

            Assert.AreEqual(
                new [] { stringType },
                ti.InferTypeArguments(new [] { tp },
                                      new [] { new ResolveResult(new ArrayType(stringType)) },
                                      new [] { new ParameterizedType(enumerableType, new [] { tp }) },
                                      out success));
            Assert.IsTrue(success);
        }
예제 #4
0
        void RunTypeInference(Candidate candidate)
        {
            if (candidate.TypeParameters == null)
            {
                if (explicitlyGivenTypeArguments != null)
                {
                    // method does not expect type arguments, but was given some
                    candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments);
                }
                // Grab new parameter types:
                ResolveParameterTypes(candidate, true);
                return;
            }
            ParameterizedType parameterizedDeclaringType = candidate.Member.DeclaringType as ParameterizedType;
            IList <IType>     classTypeArguments;

            if (parameterizedDeclaringType != null)
            {
                classTypeArguments = parameterizedDeclaringType.TypeArguments;
            }
            else
            {
                classTypeArguments = null;
            }
            // The method is generic:
            if (explicitlyGivenTypeArguments != null)
            {
                if (explicitlyGivenTypeArguments.Length == candidate.TypeParameters.Count)
                {
                    candidate.InferredTypes = explicitlyGivenTypeArguments;
                }
                else
                {
                    candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments);
                    // wrong number of type arguments given, so truncate the list or pad with UnknownType
                    candidate.InferredTypes = new IType[candidate.TypeParameters.Count];
                    for (int i = 0; i < candidate.InferredTypes.Length; i++)
                    {
                        if (i < explicitlyGivenTypeArguments.Length)
                        {
                            candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i];
                        }
                        else
                        {
                            candidate.InferredTypes[i] = SpecialType.UnknownType;
                        }
                    }
                }
            }
            else
            {
                TypeInference ti = new TypeInference(compilation, conversions);
                bool          success;
                candidate.InferredTypes = ti.InferTypeArguments(candidate.TypeParameters, arguments, candidate.ParameterTypes, out success, classTypeArguments);
                if (!success)
                {
                    candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed);
                }
            }
            // Now substitute in the formal parameters:
            var substitution = new ConstraintValidatingSubstitution(classTypeArguments, candidate.InferredTypes, this);

            for (int i = 0; i < candidate.ParameterTypes.Length; i++)
            {
                candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution);
            }
            if (!substitution.ConstraintsValid)
            {
                candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint);
            }
        }
예제 #5
0
		void RunTypeInference(Candidate candidate)
		{
			IMethod method = candidate.Member as IMethod;
			if (method == null || method.TypeParameters.Count == 0) {
				if (explicitlyGivenTypeArguments != null) {
					// method does not expect type arguments, but was given some
					candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments);
				}
				return;
			}
			ParameterizedType parameterizedDeclaringType = candidate.Member.DeclaringType as ParameterizedType;
			IList<IType> classTypeArguments;
			if (parameterizedDeclaringType != null) {
				classTypeArguments = parameterizedDeclaringType.TypeArguments;
			} else {
				classTypeArguments = null;
			}
			// The method is generic:
			if (explicitlyGivenTypeArguments != null) {
				if (explicitlyGivenTypeArguments.Length == method.TypeParameters.Count) {
					candidate.InferredTypes = explicitlyGivenTypeArguments;
				} else {
					candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments);
					// wrong number of type arguments given, so truncate the list or pad with UnknownType
					candidate.InferredTypes = new IType[method.TypeParameters.Count];
					for (int i = 0; i < candidate.InferredTypes.Length; i++) {
						if (i < explicitlyGivenTypeArguments.Length)
							candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i];
						else
							candidate.InferredTypes[i] = SpecialType.UnknownType;
					}
				}
			} else {
				TypeInference ti = new TypeInference(compilation, conversions);
				bool success;
				candidate.InferredTypes = ti.InferTypeArguments(candidate.TypeParameters, arguments, candidate.ParameterTypes, out success, classTypeArguments);
				if (!success)
					candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed);
			}
			// Now substitute in the formal parameters:
			var substitution = new ConstraintValidatingSubstitution(classTypeArguments, candidate.InferredTypes, this);
			for (int i = 0; i < candidate.ParameterTypes.Length; i++) {
				candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution);
			}
			if (!substitution.ConstraintsValid)
				candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint);
		}
예제 #6
0
		static bool IsEligibleExtensionMethod(ICompilation compilation, CSharpConversions conversions, IType targetType, IMethod method, bool useTypeInference, out IType[] outInferredTypes)
		{
			outInferredTypes = null;
			if (targetType == null)
				return true;
			if (method.Parameters.Count == 0)
				return false;
			IType thisParameterType = method.Parameters[0].Type;
			if (useTypeInference && method.TypeParameters.Count > 0) {
				// We need to infer type arguments from targetType:
				TypeInference ti = new TypeInference(compilation, conversions);
				ResolveResult[] arguments = { new ResolveResult(targetType) };
				IType[] parameterTypes = { method.Parameters[0].Type };
				bool success;
				var inferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, parameterTypes, out success);
				var substitution = new TypeParameterSubstitution(null, inferredTypes);
				// Validate that the types that could be inferred (aren't unknown) satisfy the constraints:
				bool hasInferredTypes = false;
				for (int i = 0; i < inferredTypes.Length; i++) {
					if (inferredTypes[i].Kind != TypeKind.Unknown && inferredTypes[i].Kind != TypeKind.UnboundTypeArgument) {
						hasInferredTypes = true;
						if (!OverloadResolution.ValidateConstraints(method.TypeParameters[i], inferredTypes[i], substitution, conversions))
							return false;
					} else {
						inferredTypes[i] = method.TypeParameters[i]; // do not substitute types that could not be inferred
					}
				}
				if (hasInferredTypes)
					outInferredTypes = inferredTypes;
				thisParameterType = thisParameterType.AcceptVisitor(substitution);
			}
			Conversion c = conversions.ImplicitConversion(targetType, thisParameterType);
			return c.IsValid && (c.IsIdentityConversion || c.IsReferenceConversion || c.IsBoxingConversion);
		}