/// <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); }
public void ResolveArrayTypeReference(ArrayTypeReference node) { if (node.Entity != null) { return; } ResolveTypeReference(node.ElementType); IType elementType = TypeSystemServices.GetType(node.ElementType); if (TypeSystemServices.IsError(elementType)) { node.Entity = TypeSystemServices.ErrorEntity; } else { int rank = null == node.Rank ? 1 : (int)node.Rank.Value; node.Entity = _context.TypeSystemServices.GetArrayType(elementType, rank); } }
/// <summary> /// Constructs an entity from a generic definition and arguments, after ensuring the construction is valid. /// </summary> /// <param name="definition">The generic definition entity.</param> /// <param name="node">The node in which construction occurs.</param> /// <param name="argumentNodes">The nodes of the arguments supplied for generic construction.</param> /// <returns>The constructed entity.</returns> public IEntity ConstructEntity(IEntity definition, Node constructionNode, TypeReferenceCollection argumentNodes) { // Ensure definition is a valid entity if (definition == null || TypeSystemServices.IsError(definition)) { return(TypeSystemServices.ErrorEntity); } // Ambiguous generic constructions are handled separately if (definition.EntityType == EntityType.Ambiguous) { return(ConstructAmbiguousEntity((Ambiguous)definition, constructionNode, argumentNodes)); } // Check that the construction is valid if (!CheckGenericConstruction(definition, constructionNode, argumentNodes, Errors)) { return(TypeSystemServices.ErrorEntity); } // Construct a type or a method according to the definition IType[] arguments = Array.ConvertAll <TypeReference, IType>( argumentNodes.ToArray(), delegate(TypeReference tr) { return((IType)tr.Entity); }); if (IsGenericType(definition)) { return(((IType)definition).GenericInfo.ConstructType(arguments)); } if (IsGenericMethod(definition)) { return(((IMethod)definition).GenericInfo.ConstructMethod(arguments)); } // Should never be reached - if definition is neither a generic type nor a generic method, // CheckGenericConstruction would've indicated this return(TypeSystemServices.ErrorEntity); }