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