/// <summary> /// Validates that it will be possible to create an EEType for '<paramref name="type"/>'. /// </summary> public static void CheckCanGenerateEEType(NodeFactory factory, TypeDesc type) { // Don't validate generic definitons if (type.IsGenericDefinition) { return; } // System.__Canon or System.__UniversalCanon if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any)) { return; } // It must be possible to create an EEType for the base type of this type TypeDesc baseType = type.BaseType; if (baseType != null) { // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(GetFullCanonicalTypeForCanonicalType(baseType)); } // We need EETypes for interfaces foreach (var intf in type.RuntimeInterfaces) { // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(GetFullCanonicalTypeForCanonicalType(intf)); } // Validate classes, structs, enums, interfaces, and delegates DefType defType = type as DefType; if (defType != null) { // Ensure we can compute the type layout defType.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields); // // The fact that we generated an EEType means that someone can call RuntimeHelpers.RunClassConstructor. // We need to make sure this is possible. // if (factory.TypeSystemContext.HasLazyStaticConstructor(defType)) { defType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizesAndFields); } // Make sure instantiation length matches the expectation // TODO: it might be more resonable for the type system to enforce this (also for methods) if (defType.Instantiation.Length != defType.GetTypeDefinition().Instantiation.Length) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } foreach (TypeDesc typeArg in defType.Instantiation) { // ByRefs, pointers, function pointers, and System.Void are never valid instantiation arguments if (typeArg.IsByRef || typeArg.IsPointer || typeArg.IsFunctionPointer || typeArg.IsVoid || (typeArg.IsValueType && ((DefType)typeArg).IsByRefLike)) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // TODO: validate constraints } // Check the type doesn't have bogus MethodImpls or overrides and we can get the finalizer. defType.GetFinalizer(); } // Validate parameterized types ParameterizedType parameterizedType = type as ParameterizedType; if (parameterizedType != null) { TypeDesc parameterType = parameterizedType.ParameterType; // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(parameterType); if (parameterizedType.IsArray) { if (parameterType.IsFunctionPointer) { // Arrays of function pointers are not currently supported throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } LayoutInt elementSize = parameterType.GetElementSize(); if (!elementSize.IsIndeterminate && elementSize.AsInt >= ushort.MaxValue) { // Element size over 64k can't be encoded in the GCDesc throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadValueClassTooLarge, parameterType); } if (((ArrayType)parameterizedType).Rank > 32) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadRankTooLarge, type); } if ((parameterType.IsDefType) && ((DefType)parameterType).IsByRefLike) { // Arrays of byref-like types are not allowed throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } } // Validate we're not constructing a type over a ByRef if (parameterType.IsByRef) { // CLR compat note: "ldtoken int32&&" will actually fail with a message about int32&; "ldtoken int32&[]" // will fail with a message about being unable to create an array of int32&. This is a middle ground. throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // It might seem reasonable to disallow array of void, but the CLR doesn't prevent that too hard. // E.g. "newarr void" will fail, but "newarr void[]" or "ldtoken void[]" will succeed. } // Function pointer EETypes are not currently supported if (type.IsFunctionPointer) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } }