Example #1
0
		private TypeInference Invert(TypeInference inference)
		{
			switch (inference)
			{
				case TypeInference.AllowCovariance:
					return TypeInference.AllowContravariance;

				case TypeInference.AllowContravariance:
					return TypeInference.AllowCovariance;

				default:
					return TypeInference.Exact;
			}
		}
Example #2
0
		private bool InferArrayType(IArrayType formalType, IType actualType, TypeInference inference)
		{
			IArrayType actualArrayType = actualType as IArrayType;
			return
				(actualArrayType != null) &&
				(actualArrayType.Rank == formalType.Rank) &&
				(Infer(formalType.ElementType, actualType.ElementType, inference));
		}
Example #3
0
		private bool InferSimpleType(IType formalType, IType actualType, TypeInference inference)
		{
			// Inference has no effect on formal parameter types that are not generic parameters
			return true;
		}
Example #4
0
		private bool InferCallableType(ICallableType formalType, IType actualType, TypeInference inference)
		{
			ICallableType callableActualType = actualType as ICallableType;
			if (callableActualType == null) return false;

			CallableSignature formalSignature = formalType.GetSignature();
			CallableSignature actualSignature = callableActualType.GetSignature();

			if (formalSignature.AcceptVarArgs)
			{
				if (actualSignature.Parameters.Length < formalSignature.Parameters.Length)
					return false;
			}
			else if (formalSignature.Parameters.Length != actualSignature.Parameters.Length)
			{
				return false;
			}

			// Infer return type, maintaining inference direction
			if (!Infer(formalSignature.ReturnType, actualSignature.ReturnType, inference))
			{
				return false;
			}

			// Infer parameter types, inverting inference direction
			for (int i = 0; i < formalSignature.Parameters.Length; ++i)
			{
				bool inferenceSuccessful = Infer(
					formalSignature.Parameters[i].Type,
					actualSignature.Parameters[i].Type,
					Invert(inference));

				if (!inferenceSuccessful) return false;
			}
			return true;
		}
Example #5
0
		private bool InferConstructedType(IType formalType, IType actualType, TypeInference inference)
		{
			// look for a single occurance of the formal 
			// constructed type in the actual type's hierarchy 
			IType constructedActualType = GenericsServices.FindConstructedType(
				actualType,
				formalType.ConstructedInfo.GenericDefinition);

			if (constructedActualType == null)
			{
				return false;
			}

			// Exact inference requires the constructed occurance to be
			// the actual type itself
			if (inference == TypeInference.Exact && actualType != constructedActualType)
			{
				return false;
			}

			for (int i = 0; i < formalType.ConstructedInfo.GenericArguments.Length; ++i)
			{
				bool inferenceSuccessful = Infer(
					formalType.ConstructedInfo.GenericArguments[i],
					constructedActualType.ConstructedInfo.GenericArguments[i],
					TypeInference.Exact); // Generic arguments must match exactly, no variance allowed

				if (!inferenceSuccessful) return false;
			}
			return true;
		}
Example #6
0
		/// <summary>
		/// Attempts to infer the type of generic parameters that occur in a formal parameter type
		/// according to its actual argument type. 
		/// </summary>
		/// <returns>False if inference failed; otherwise, true. </returns>
		protected bool Infer(IType formalType, IType actualType, TypeInference inference)
		{
			// Skip unspecified actual types
			if (actualType == null)
				return true;

			IGenericParameter gp = formalType as IGenericParameter;
			if (null != gp)
			{
				return InferGenericParameter(gp, actualType, inference);
			}

			ICallableType callableType = formalType as ICallableType;
			if (null != callableType)
			{
				return InferCallableType(callableType, actualType, inference);
			}

			if (formalType.ConstructedInfo != null)
			{
				return InferConstructedType(formalType, actualType, inference);
			}

			IArrayType arrayType = formalType as IArrayType;
			if (null != arrayType)
			{
				return InferArrayType(arrayType, actualType, inference);
			}

			return InferSimpleType(formalType, actualType, inference);
		}
Example #7
0
		protected virtual bool InferGenericParameter(IGenericParameter formalType, IType actualType, TypeInference inference)
		{
			if (InferredTypes.ContainsKey(formalType))
			{
				InferredType inferredType = InferredTypes[formalType];
				if ((inference & TypeInference.AllowContravariance) != TypeInference.AllowContravariance)
				{
					inferredType.ApplyLowerBound(actualType);
				}
				if ((inference & TypeInference.AllowCovariance) != TypeInference.AllowCovariance)
				{
					inferredType.ApplyUpperBound(actualType);
				}
			}

			return true;
		}
        /// <summary>
        /// Resolves an array creation.
        /// </summary>
        /// <param name="elementType">
        /// The array element type.
        /// Pass null to resolve an implicitly-typed array creation.
        /// </param>
        /// <param name="sizeArguments">
        /// The size arguments.
        /// The length of this array will be used as the number of dimensions of the array type.
        /// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
        /// </param>
        /// <param name="initializerElements">
        /// The initializer elements. May be null if no array initializer was specified.
        /// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
        /// </param>
        public ArrayCreateResolveResult ResolveArrayCreation(IType elementType, ResolveResult[] sizeArguments, ResolveResult[] initializerElements = null)
        {
            int dimensions = sizeArguments.Length;
            if (dimensions == 0)
                throw new ArgumentException("sizeArguments.Length must not be 0");
            if (elementType == null) {
                TypeInference typeInference = new TypeInference(compilation, conversions);
                bool success;
                elementType = typeInference.GetBestCommonType(initializerElements, out success);
            }
            IType arrayType = new ArrayType(compilation, elementType, dimensions);

            AdjustArrayAccessArguments(sizeArguments);

            if (initializerElements != null) {
                for (int i = 0; i < initializerElements.Length; i++) {
                    initializerElements[i] = Convert(initializerElements[i], elementType);
                }
            }
            return new ArrayCreateResolveResult(arrayType, sizeArguments, initializerElements);
        }
        protected override bool InferGenericParameter(IGenericParameter formalType, IType actualType, TypeInference inference)
        {
            // Generic parameters occuring in closures are a result of untyped input types and should be skipped
            if (_currentClosure != null && actualType == formalType) return true;

            return base.InferGenericParameter(formalType, actualType, inference);
        }
 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);
 }
Example #11
0
        private VariableDefinition GetVarDefinition(VarDeclaration declaration)
        {
            var type = TypeInference.InferType(declaration, _context);

            return(new VariableDefinition(declaration.GetUniqueVarName(), type, _methodBody));
        }
Example #12
0
 private bool InferSimpleType(IType formalType, IType actualType, TypeInference inference)
 {
     // Inference has no effect on formal parameter types that are not generic parameters
     return(true);
 }
Example #13
0
        protected virtual bool InferGenericParameter(IGenericParameter formalType, IType actualType, TypeInference inference)
        {
            if (InferredTypes.ContainsKey(formalType))
            {
                InferredType inferredType = InferredTypes[formalType];
                if ((inference & TypeInference.AllowContravariance) != TypeInference.AllowContravariance)
                {
                    inferredType.ApplyLowerBound(actualType);
                }
                if ((inference & TypeInference.AllowCovariance) != TypeInference.AllowCovariance)
                {
                    inferredType.ApplyUpperBound(actualType);
                }
            }

            return(true);
        }
        public void InferFloatTests()
        {
            var FloatTestInitialContext = new InferenceState(new FreshVariableStream(),
                                                             new TermVariableBinding("zero", new TypeScheme(new FloatType(new UnitPower(new TypeVariable("x"), 1)), ("x", Kind.Unit))),
                                                             new TermVariableBinding("one", new TypeScheme(new FloatType(new UnitIdentity()))),
                                                             new TermVariableBinding("mass", new TypeScheme(new FloatType(new UnitPower(new PrimitiveUnit("kg"), 1)))),
                                                             new TermVariableBinding("time", new TypeScheme(new FloatType(new UnitPower(new PrimitiveUnit("sec"), 1)))),
                                                             new TermVariableBinding("mul", new TypeScheme(new ArrowType(
                                                                                                               new FloatType(new UnitPower(new TypeVariable("a"), 1)),
                                                                                                               new FloatType(new UnitPower(new TypeVariable("b"), 1)),
                                                                                                               new FloatType(new UnitMultiply(new UnitPower(new TypeVariable("a"), 1), new UnitPower(new TypeVariable("b"), 1)))), ("a", Kind.Unit), ("b", Kind.Unit))),
                                                             new TermVariableBinding("plus", new TypeScheme(new ArrowType(
                                                                                                                new FloatType(new UnitPower(new TypeVariable("a"), 1)),
                                                                                                                new FloatType(new UnitPower(new TypeVariable("a"), 1)),
                                                                                                                new FloatType(new UnitPower(new TypeVariable("a"), 1))), ("a", Kind.Unit))),
                                                             new TermVariableBinding("div", new TypeScheme(new ArrowType(
                                                                                                               new FloatType(new UnitMultiply(new UnitPower(new TypeVariable("a"), 1), new UnitPower(new TypeVariable("b"), 1))),
                                                                                                               new FloatType(new UnitPower(new TypeVariable("a"), 1)),
                                                                                                               new FloatType(new UnitPower(new TypeVariable("b"), 1))),
                                                                                                           ("a", Kind.Unit), ("b", Kind.Unit))),
                                                             new TermVariableBinding("pair", new TypeScheme(new ArrowType(
                                                                                                                new FloatType(new UnitPower(new TypeVariable("a"), 1)),
                                                                                                                new FloatType(new UnitPower(new TypeVariable("b"), 1)),
                                                                                                                new FloatType(new UnitPower(new TypeVariable("a"), 1)),
                                                                                                                new FloatType(new UnitPower(new TypeVariable("b"), 1))),
                                                                                                            ("a", Kind.Unit), ("b", Kind.Unit)))
                                                             );

            Assert.AreEqual(
                TypeInference.Infer(FloatTestInitialContext, new TermVariable("zero")),
                new FloatType(new UnitPower(new TypeVariable("t0"), 1)));

            Assert.AreEqual(
                TypeInference.Infer(FloatTestInitialContext, new Application(new TermVariable("mul"), new TermVariable("mass"), new TermVariable("mass"))),
                new FloatType(new UnitPower(new PrimitiveUnit("kg"), 2)));

            Assert.AreEqual(
                TypeInference.Infer(FloatTestInitialContext,
                                    new LambdaAbstraction("a",
                                                          new LambdaAbstraction("b",
                                                                                new Application(new TermVariable("plus"), new TermVariable("a"), new TermVariable("b"))))),
                new ArrowType(new FloatType(new UnitPower(new TypeVariable("h0"), 1)),
                              new FloatType(new UnitPower(new TypeVariable("h0"), 1)),
                              new FloatType(new UnitPower(new TypeVariable("h0"), 1))));

            Assert.AreEqual(
                TypeInference.Infer(FloatTestInitialContext,
                                    new LambdaAbstraction("x",
                                                          new LetBinding("d", new Application(new TermVariable("div"), new TermVariable("x")),
                                                                         new Application(new TermVariable("pair"),
                                                                                         new Application(new TermVariable("d"), new TermVariable("mass")),
                                                                                         new Application(new TermVariable("d"), new TermVariable("time")))))),
                new ArrowType(new FloatType(new UnitPower(new TypeVariable("h0"), 1)),
                              new FloatType(new UnitMultiply(new UnitPower(new TypeVariable("h0"), 1), new UnitPower(new PrimitiveUnit("kg"), -1))),
                              new FloatType(new UnitMultiply(new UnitPower(new TypeVariable("h0"), 1), new UnitPower(new PrimitiveUnit("sec"), -1)))));

            Assert.AreEqual(
                TypeInference.Infer(FloatTestInitialContext,
                                    new LetBinding("recip", new Application(new TermVariable("div"), new TermVariable("one")),
                                                   new Application(new TermVariable("pair"),
                                                                   new Application(new TermVariable("recip"), new TermVariable("mass")),
                                                                   new Application(new TermVariable("recip"), new TermVariable("time"))))),
                new ArrowType(new FloatType(new UnitPower(new PrimitiveUnit("kg"), -1)), new FloatType(new UnitPower(new PrimitiveUnit("sec"), -1))));
        }