/// <summary>
/// Checks if a specified type argument violates the constraints
/// declared on a specified type paramter.
/// </summary>
public bool ViolatesParameterConstraints(IGenericParameter parameter, TypeReference argumentNode)
{
IType argument = TypeSystemServices.GetEntity(argumentNode) as IType;
// Ensure argument is a valid type
if (argument == null || TypeSystemServices.IsError(argument))
{
return(false);
}
bool valid = true;
// Check type semantics constraints
if (parameter.IsClass && !argument.IsClass)
{
Errors.Add(CompilerErrorFactory.GenericArgumentMustBeReferenceType(ConstructionNode, parameter, argument));
valid = false;
}
if (parameter.IsValueType && !argument.IsValueType)
{
Errors.Add(CompilerErrorFactory.GenericArgumentMustBeValueType(argumentNode, parameter, argument));
valid = false;
}
// Check for default constructor
if (parameter.MustHaveDefaultConstructor && !HasDefaultConstructor(argument))
{
Errors.Add(CompilerErrorFactory.GenericArgumentMustHaveDefaultConstructor(argumentNode, parameter, argument));
valid = false;
}
// Check base type constraints
IType[] baseTypes = parameter.GetTypeConstraints();
if (baseTypes != null)
{
foreach (IType baseType in baseTypes)
{
// Don't check for System.ValueType supertype constraint
// if parameter also has explicit value type constraint
if (baseType == _tss.ValueTypeType && parameter.IsValueType)
{
continue;
}
if (!baseType.IsAssignableFrom(argument))
{
Errors.Add(CompilerErrorFactory.GenericArgumentMustHaveBaseType(argumentNode, parameter, argument, baseType));
valid = false;
}
}
}
return(!valid);
}