private void LowerBoundInference(CType pSource, CType pDest)
{
// SPEC: A lower-bound inference from a CType U to a CType V is made as follows:
// SPEC: If V is one of the unfixed Xi then U is added to the set of
// SPEC: lower bounds for Xi.
if (LowerBoundTypeParameterInference(pSource, pDest))
{
return;
}
// SPEC: Otherwise, if U is an array CType Ue[...] and V is either an array
// SPEC: CType Ve[...] of the same rank, or if U is a one-dimensional array
// SPEC: CType Ue[] and V is one of IEnumerable<Ve>, ICollection<Ve> or
// SPEC: IList<Ve> then
// SPEC: if Ue is known to be a reference CType then a lower-bound inference
// SPEC: from Ue to Ve is made.
// SPEC: otherwise an exact inference from Ue to Ve is made.
if (LowerBoundArrayInference(pSource, pDest))
{
return;
}
// SPEC: Otherwise, if V is nullable CType V1? and U is nullable CType U1?
// SPEC: then an exact inference is made from U1 to V1.
if (ExactNullableInference(pSource, pDest))
{
return;
}
// At this point we could also do an inference from non-nullable U
// to nullable V.
//
// We tried implementing lower bound nullable inference as follows:
//
// Otherwise, if V is nullable CType V1? and U is a non-nullable
// struct CType then an exact inference is made from U to V1.
//
// However, this causes an unfortunate interaction with
// our implementation of section 15.2 of
// the specification. Namely, it appears that the code which
// checks whether a given method is compatible with
// a delegate CType assumes that if method CType inference succeeds,
// then the inferred types are compatible with the delegate types.
// This is not necessarily so; the inferred types could be compatible
// via a conversion other than reference or identity.
//
// We should take an action item to investigate this problem.
// Until then, we will turn off the proposed lower bound nullable
// inference.
// if (LowerBoundNullableInference(pSource, pDest))
// {
// return;
// }
// SPEC: Otherwise... many cases for constructed generic types.
if (LowerBoundConstructedInference(pSource, pDest))
{
return;
}
// SPEC: Otherwise, no inferences are made.
}