public static bool TypeContainsTyVars(CType type, TypeArray typeVars)
{
LRecurse: // Label used for "tail" recursion.
switch (type.GetTypeKind())
{
default:
Debug.Assert(false, "Bad Symbol kind in TypeContainsTyVars");
return false;
case TypeKind.TK_UnboundLambdaType:
case TypeKind.TK_BoundLambdaType:
case TypeKind.TK_NullType:
case TypeKind.TK_VoidType:
case TypeKind.TK_OpenTypePlaceholderType:
case TypeKind.TK_MethodGroupType:
return false;
case TypeKind.TK_ArrayType:
case TypeKind.TK_NullableType:
case TypeKind.TK_ParameterModifierType:
case TypeKind.TK_PointerType:
type = type.GetBaseOrParameterOrElementType();
goto LRecurse;
case TypeKind.TK_AggregateType:
{ // BLOCK
AggregateType ats = type.AsAggregateType();
for (int i = 0; i < ats.GetTypeArgsAll().Size; i++)
{
if (TypeContainsTyVars(ats.GetTypeArgsAll().Item(i), typeVars))
{
return true;
}
}
}
return false;
case TypeKind.TK_ErrorType:
if (type.AsErrorType().HasParent())
{
ErrorType err = type.AsErrorType();
Debug.Assert(err.nameText != null && err.typeArgs != null);
for (int i = 0; i < err.typeArgs.Size; i++)
{
if (TypeContainsTyVars(err.typeArgs.Item(i), typeVars))
{
return true;
}
}
if (err.HasTypeParent())
{
type = err.GetTypeParent();
goto LRecurse;
}
}
return false;
case TypeKind.TK_TypeParameterType:
if (typeVars != null && typeVars.Size > 0)
{
int ivar = type.AsTypeParameterType().GetIndexInTotalParameters();
return ivar < typeVars.Size && type == typeVars.Item(ivar);
}
return true;
}
}