| File: Internal\Reflection\Execution\TypeLoader\ConstraintValidator.cs | Web Access |
| Project: src\runtime\src\coreclr\nativeaot\System.Private.Reflection.Execution\src\System.Private.Reflection.Execution.csproj (System.Private.Reflection.Execution) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Reflection; using Debug = global::System.Diagnostics.Debug; namespace Internal.Reflection.Execution { internal static partial class ConstraintValidator { private static bool SatisfiesConstraints(this Type genericVariable, SigTypeContext typeContextOfConstraintDeclarer, Type typeArg) { GenericParameterAttributes attributes = genericVariable.GenericParameterAttributes; if ((attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) { if (!typeArg.IsValueType) { return false; } else { // the type argument is a value type, however if it is any kind of Nullable we want to fail // as the constraint accepts any value type except Nullable types (Nullable itself is a value type) if (typeArg.IsNullable()) return false; } } if ((attributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0) { if (typeArg.IsValueType) return false; } if ((attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0) { if (!typeArg.HasExplicitOrImplicitPublicDefaultConstructor() || typeArg.IsAbstract) return false; } if (typeArg.IsByRefLike && (attributes & (GenericParameterAttributes)0x20 /* GenericParameterAttributes.AllowByRefLike */) == 0) return false; // Now check general subtype constraints foreach (var constraint in genericVariable.GetGenericParameterConstraints()) { Type instantiatedTypeConstraint = constraint.Instantiate(typeContextOfConstraintDeclarer); // System.Object constraint will be always satisfied - even if argList is empty if (instantiatedTypeConstraint.IsSystemObject()) continue; // if a concrete type can be cast to the constraint, then this constraint will be satisfied if (!AreTypesAssignableInternal(typeArg, instantiatedTypeConstraint, fBoxedSource: true, fAllowSizeEquivalence: false)) return false; } return true; } private static void EnsureSatisfiesClassConstraints(Type[] typeParameters, Type[] typeArguments, object definition, SigTypeContext typeContext) { if (typeParameters.Length != typeArguments.Length) { throw new ArgumentException(SR.Argument_GenericArgsCount); } // Do sanity validation of all arguments first. The actual constraint validation can fail in unexpected ways // if it hits SigTypeContext with these never valid types. for (int i = 0; i < typeParameters.Length; i++) { Type actualArg = typeArguments[i]; if (actualArg.IsSystemVoid() || (actualArg.HasElementType && !actualArg.IsArray) || actualArg.IsFunctionPointer) { throw new ArgumentException(SR.Format(SR.Argument_NeverValidGenericArgument, actualArg)); } } for (int i = 0; i < typeParameters.Length; i++) { Type formalArg = typeParameters[i]; Type actualArg = typeArguments[i]; if (!formalArg.SatisfiesConstraints(typeContext, actualArg)) { throw new ArgumentException(SR.Format(SR.Argument_ConstraintFailed, actualArg, definition.ToString(), formalArg)); } } } public static void EnsureSatisfiesClassConstraints(Type typeDefinition, Type[] typeArguments) { Type[] typeParameters = typeDefinition.GetGenericArguments(); SigTypeContext typeContext = new SigTypeContext(typeArguments, null); EnsureSatisfiesClassConstraints(typeParameters, typeArguments, typeDefinition, typeContext); } public static void EnsureSatisfiesClassConstraints(MethodInfo reflectionMethodInfo) { MethodInfo genericMethodDefinition = reflectionMethodInfo.GetGenericMethodDefinition(); Type[] methodArguments = reflectionMethodInfo.GetGenericArguments(); Type[] methodParameters = genericMethodDefinition.GetGenericArguments(); Type[] typeArguments = reflectionMethodInfo.DeclaringType.GetGenericArguments(); SigTypeContext typeContext = new SigTypeContext(typeArguments, methodArguments); EnsureSatisfiesClassConstraints(methodParameters, methodArguments, genericMethodDefinition, typeContext); } } }