Пример #1
0
        public override Type[] InferMethodArguments(ParseContext ec, MethodBase method)
        {
            Type[] method_generic_args   = method.GetGenericArguments();
            TypeInferenceContext context = new TypeInferenceContext(method_generic_args);

            if (!context.UnfixedVariableExists)
            {
                return(Type.EmptyTypes);
            }

            ParametersCollection pd = TypeManager.GetParameterData(method);

            if (!InferInPhases(ec, context, pd))
            {
                return(null);
            }

            return(context.InferredTypeArguments);
        }
Пример #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));
        }