/// <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); }
/// <summary> /// Checks if a specified type argument violates the constraints /// declared on a specified type paramter. /// </summary> public bool ViolatesParameterConstraints(IGenericParameter parameter, IType argument) { // 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(ConstructionNode, parameter, argument)); valid = false; } if (parameter.MustHaveDefaultConstructor && !HasDefaultConstructor(argument)) { Errors.Add(CompilerErrorFactory.GenericArgumentMustHaveDefaultConstructor(ConstructionNode, 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(ConstructionNode, parameter, argument, baseType)); valid = false; } } } return !valid; }
private bool MaintainsParameterConstraints(IGenericParameter parameter, IType argument) { if (argument == null || TypeSystemServices.IsError(argument)) return true; if (argument == parameter) return true; if (argument == _typeSystemServices.VoidType) { Errors.Add(CompilerErrorFactory.InvalidGenericParameterType(ConstructionNode, argument)); return false; } bool valid = true; // Check type semantics constraints if (parameter.IsClass && !(argument.IsClass || argument.IsInterface)) { Errors.Add(CompilerErrorFactory.GenericArgumentMustBeReferenceType(ConstructionNode, parameter, argument)); valid = false; } if (parameter.IsValueType && !argument.IsValueType) { Errors.Add(CompilerErrorFactory.GenericArgumentMustBeValueType(ConstructionNode, parameter, argument)); valid = false; } // Don't check for default constructor constraint if value type constraint failed else if (parameter.MustHaveDefaultConstructor && !HasDefaultConstructor(argument)) { Errors.Add(CompilerErrorFactory.GenericArgumentMustHaveDefaultConstructor(ConstructionNode, parameter, argument)); valid = false; } // Check base type constraints IType[] baseTypes = parameter.GetTypeConstraints(); if (baseTypes != null) { foreach (IType baseType in baseTypes) { // Foo<T> where T : Foo<T> if (null != _definition && TypeCompatibilityRules.IsAssignableFrom(baseType, _definition) && argument == _constructionNode.ParentNode.Entity) continue; // Don't check for System.ValueType supertype constraint // if parameter also has explicit value type constraint if (baseType == _typeSystemServices.ValueTypeType && parameter.IsValueType) continue; if (!TypeCompatibilityRules.IsAssignableFrom(baseType, argument)) { Errors.Add(CompilerErrorFactory.GenericArgumentMustHaveBaseType(ConstructionNode, parameter, argument, baseType)); valid = false; } } } return valid; }
private bool MaintainsParameterConstraints(IGenericParameter parameter, IType argument) { if (argument == null || TypeSystemServices.IsError(argument)) { return(true); } if (argument == parameter) { return(true); } if (argument == _typeSystemServices.VoidType) { Errors.Add(CompilerErrorFactory.InvalidGenericParameterType(ConstructionNode, argument)); return(false); } bool valid = true; // Check type semantics constraints if (parameter.IsClass && !(argument.IsClass || argument.IsInterface)) { Errors.Add(CompilerErrorFactory.GenericArgumentMustBeReferenceType(ConstructionNode, parameter, argument)); valid = false; } if (parameter.IsValueType && !argument.IsValueType) { Errors.Add(CompilerErrorFactory.GenericArgumentMustBeValueType(ConstructionNode, parameter, argument)); valid = false; } // Don't check for default constructor constraint if value type constraint failed else if (parameter.MustHaveDefaultConstructor && !HasDefaultConstructor(argument)) { Errors.Add(CompilerErrorFactory.GenericArgumentMustHaveDefaultConstructor(ConstructionNode, parameter, argument)); valid = false; } // Check base type constraints IType[] baseTypes = parameter.GetTypeConstraints(); if (baseTypes != null) { foreach (IType baseType in baseTypes) { // Foo<T> where T : Foo<T> if (null != _definition && TypeCompatibilityRules.IsAssignableFrom(baseType, _definition) && argument == _constructionNode.ParentNode.Entity) { continue; } // Don't check for System.ValueType supertype constraint // if parameter also has explicit value type constraint if (baseType == _typeSystemServices.ValueTypeType && parameter.IsValueType) { continue; } if (!TypeCompatibilityRules.IsAssignableFrom(baseType, argument)) { Errors.Add(CompilerErrorFactory.GenericArgumentMustHaveBaseType(ConstructionNode, parameter, argument, baseType)); valid = false; } } } return(valid); }