예제 #1
0
        bool DoSecondPhase(ParseContext ec, TypeInferenceContext tic, Type[] methodParameters, bool fixDependent)
        {
            var fixedAny = false;

            if (fixDependent && !tic.FixDependentTypes(ec, ref fixedAny))
            {
                return(false);
            }

            // If no further unfixed type variables exist, type inference succeeds
            if (!tic.UnfixedVariableExists)
            {
                return(true);
            }

            if (!fixedAny && fixDependent)
            {
                return(false);
            }

            // For all arguments where the corresponding argument output types
            // contain unfixed type variables but the input types do not,
            // an output type inference is made
            for (int i = 0; i < arg_count; i++)
            {
                // Align params arguments
                Type iType = methodParameters[i >= methodParameters.Length ? methodParameters.Length - 1 : i];

                if (!TypeManager.IsDelegateType(iType))
                {
                    if (TypeManager.DropGenericTypeArguments(iType) != TypeManager.CoreTypes.GenericExpression)
                    {
                        continue;
                    }

                    iType = iType.GetGenericArguments()[0];
                }

                var methodInfo = iType.GetMethod("Invoke");
                var returnType = methodInfo.ReturnType;

                if (returnType.IsGenericParameter)
                {
                    // Blablabla, because reflection does not work with dynamic types
                    var genericArguments = iType.GetGenericArguments();
                    returnType = genericArguments[returnType.GenericParameterPosition];
                }

                if (tic.IsReturnTypeNonDependent(ec, methodInfo, returnType))
                {
                    score -= tic.OutputTypeInference(ec, arguments[i].Value, iType);
                }
            }


            return(DoSecondPhase(ec, tic, methodParameters, true));
        }
예제 #2
0
        //
        // Implements method type arguments inference
        //
        bool InferInPhases(ParseContext ec, TypeInferenceContext tic, ParametersCollection methodParameters)
        {
            int paramsArgumentsStart;

            if (methodParameters.HasParams)
            {
                paramsArgumentsStart = methodParameters.Count - 1;
            }
            else
            {
                paramsArgumentsStart = arg_count;
            }

            Type[] ptypes = methodParameters.Types;

            //
            // The first inference phase
            //
            Type methodParameter = null;

            for (int i = 0; i < arg_count; i++)
            {
                Argument a = arguments[i];
                if (a == null)
                {
                    continue;
                }

                if (i < paramsArgumentsStart)
                {
                    methodParameter = methodParameters.Types[i];
                }
                else if (i == paramsArgumentsStart)
                {
                    if (arg_count == paramsArgumentsStart + 1 && TypeManager.HasElementType(a.Value.Type))
                    {
                        methodParameter = methodParameters.Types[paramsArgumentsStart];
                    }
                    else
                    {
                        methodParameter = methodParameters.Types[paramsArgumentsStart].GetElementType();
                    }

                    ptypes    = (Type[])ptypes.Clone();
                    ptypes[i] = methodParameter;
                }

                //
                // When a lambda expression, an anonymous method
                // is used an explicit argument type inference takes a place
                //
                var am = a.Value as LambdaExpression;
                if (am != null)
                {
                    if (am.ExplicitTypeInference(ec, tic, methodParameter))
                    {
                        --score;
                    }
                    continue;
                }

                if (a.IsByRef)
                {
                    score -= tic.ExactInference(a.Value.Type, methodParameter);
                    continue;
                }

                if (a.Value.Type == TypeManager.CoreTypes.Null)
                {
                    continue;
                }

                if (TypeManager.IsValueType(methodParameter))
                {
                    score -= tic.LowerBoundInference(a.Value.Type, methodParameter);
                    continue;
                }

                //
                // Otherwise an output type inference is made
                //
                score -= tic.OutputTypeInference(ec, a.Value, methodParameter);
            }

            //
            // Part of the second phase but because it happens only once
            // we don't need to call it in cycle
            //
            var fixedAny = false;

            if (!tic.FixIndependentTypeArguments(ec, ptypes, ref fixedAny))
            {
                return(false);
            }

            return(DoSecondPhase(ec, tic, ptypes, !fixedAny));
        }