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); }
// // 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)); }