private bool InferTypeArgsSecondPhase()
{
// SPEC: The second phase proceeds as follows:
// SPEC: If no unfixed CType parameters exist then CType inference succeeds.
// SPEC: Otherwise, if there exists one or more arguments Ei with corresponding
// SPEC: parameter CType Ti such that:
// SPEC: o the output CType of Ei with CType Ti contains at least one unfixed
// SPEC: CType parameter Xj, and
// SPEC: o none of the input types of Ei with CType Ti contains any unfixed
// SPEC: CType parameter Xj,
// SPEC: then an output CType inference is made from all such Ei to Ti.
// SPEC: Whether or not the previous step actually made an inference, we must
// SPEC: now fix at least one CType parameter, as follows:
// SPEC: If there exists one or more CType parameters Xi such that
// SPEC: o Xi is unfixed, and
// SPEC: o Xi has a non-empty set of bounds, and
// SPEC: o Xi does not depend on any Xj
// SPEC: then each such Xi is fixed. If any fixing operation fails then CType
// SPEC: inference fails.
// SPEC: Otherwise, if there exists one or more CType parameters Xi such that
// SPEC: o Xi is unfixed, and
// SPEC: o Xi has a non-empty set of bounds, and
// SPEC: o there is at least one CType parameter Xj that depends on Xi
// SPEC: then each such Xi is fixed. If any fixing operation fails then
// SPEC: CType inference fails.
// SPEC: Otherwise, we are unable to make progress and there are unfixed parameters.
// SPEC: CType inference fails.
// SPEC: If CType inference neither succeeds nor fails then the second phase is
// SPEC: repeated until CType inference succeeds or fails. (Since each repetition of
// SPEC: the second phase either succeeds, fails or fixes an unfixed CType parameter,
// SPEC: the algorithm must terminate with no more repetitions than the number
// SPEC: of CType parameters.
InitializeDependencies();
while (true)
{
NewInferenceResult res = DoSecondPhase();
Debug.Assert(res != NewInferenceResult.NoProgress);
if (res == NewInferenceResult.InferenceFailed)
{
return false;
}
if (res == NewInferenceResult.Success)
{
return true;
}
// Otherwise, we made some progress last time; do it again.
}
}