private bool LowerBoundConstructedInference(CType pSource, CType pDest)
{
if (!pDest.IsAggregateType())
{
return false;
}
AggregateType pConstructedDest = pDest.AsAggregateType();
TypeArray pDestArgs = pConstructedDest.GetTypeArgsAll();
if (pDestArgs.size == 0)
{
return false;
}
// SPEC: Otherwise, if V is a constructed class or struct CType C<V1...Vk>
// SPEC: and U is C<U1...Uk> then an exact inference
// SPEC: is made from each Ui to the corresponding Vi.
// SPEC: Otherwise, if V is a constructed interface or delegate CType C<V1...Vk>
// SPEC: and U is C<U1...Uk> then an exact inference,
// SPEC: lower bound inference or upper bound inference
// SPEC: is made from each Ui to the corresponding Vi.
if (pSource.IsAggregateType() &&
pSource.AsAggregateType().GetOwningAggregate() == pConstructedDest.GetOwningAggregate())
{
if (pSource.isInterfaceType() || pSource.isDelegateType())
{
LowerBoundTypeArgumentInference(pSource.AsAggregateType(), pConstructedDest);
}
else
{
ExactTypeArgumentInference(pSource.AsAggregateType(), pConstructedDest);
}
return true;
}
// SPEC: Otherwise, if V is a class CType C<V1...Vk> and U is a class CType which
// SPEC: inherits directly or indirectly from C<U1...Uk> then an exact ...
// SPEC: ... and U is a CType parameter with effective base class ...
// SPEC: ... and U is a CType parameter with an effective base class which inherits ...
if (LowerBoundClassInference(pSource, pConstructedDest))
{
return true;
}
// SPEC: Otherwise, if V is an interface CType C<V1...Vk> and U is a class CType
// SPEC: or struct CType and there is a unique set U1...Uk such that U directly
// SPEC: or indirectly implements C<U1...Uk> then an exact ...
// SPEC: ... and U is an interface CType ...
// SPEC: ... and U is a CType parameter ...
if (LowerBoundInterfaceInference(pSource, pConstructedDest))
{
return true;
}
return false;
}