////////////////////////////////////////////////////////////////////////////////
// Determine whether the arg type satisfies the typeBnd constraint. Note that
// typeBnd could be just about any type (since we added naked type parameter
// constraints).
private static bool SatisfiesBound(CSemanticChecker checker, CType arg, CType typeBnd)
{
if (typeBnd == arg)
{
return(true);
}
switch (typeBnd.GetTypeKind())
{
default:
Debug.Assert(false, "Unexpected type.");
return(false);
case TypeKind.TK_VoidType:
case TypeKind.TK_PointerType:
case TypeKind.TK_ErrorType:
return(false);
case TypeKind.TK_ArrayType:
case TypeKind.TK_TypeParameterType:
break;
case TypeKind.TK_NullableType:
typeBnd = typeBnd.AsNullableType().GetAts(checker.GetErrorContext());
if (null == typeBnd)
{
return(true);
}
break;
case TypeKind.TK_AggregateType:
break;
}
Debug.Assert(typeBnd.IsAggregateType() || typeBnd.IsTypeParameterType() || typeBnd.IsArrayType());
switch (arg.GetTypeKind())
{
default:
return(false);
case TypeKind.TK_ErrorType:
case TypeKind.TK_PointerType:
return(false);
case TypeKind.TK_NullableType:
arg = arg.AsNullableType().GetAts(checker.GetErrorContext());
if (null == arg)
{
return(true);
}
// Fall through.
goto case TypeKind.TK_TypeParameterType;
case TypeKind.TK_TypeParameterType:
case TypeKind.TK_ArrayType:
case TypeKind.TK_AggregateType:
return(checker.GetSymbolLoader().HasBaseConversion(arg, typeBnd));
}
}