bool __CanCastByVarianceToInterfaceOrDelegate(DmdType target) { if (MetadataToken != target.MetadataToken || Module != target.Module) { return(false); } // The original code used a list to check for infinite recursion, we'll use this code unless it throws too often try { RuntimeHelpers.EnsureSufficientExecutionStack(); } catch (InsufficientExecutionStackException) { Debug.Fail("Should probably not happen often"); return(false); } var inst = GetGenericArguments(); if (inst.Count > 0) { var targetInst = target.GetGenericArguments(); var targetInstGenParams = target.GetGenericTypeDefinition().GetGenericArguments(); for (int i = 0; i < inst.Count; i++) { var thArg = inst[i]; var thTargetArg = targetInst[i]; if (!thArg.IsEquivalentTo(thTargetArg)) { switch (targetInstGenParams[i].GenericParameterAttributes & DmdGenericParameterAttributes.VarianceMask) { case DmdGenericParameterAttributes.Covariant: if (!thArg.__IsBoxedAndCanCastTo(thTargetArg)) { return(false); } break; case DmdGenericParameterAttributes.Contravariant: if (!thTargetArg.__IsBoxedAndCanCastTo(thArg)) { return(false); } break; case DmdGenericParameterAttributes.None: return(false); default: return(false); } } } } return(true); }
static DmdType GetGenericTypeDefinition(DmdType type) { if (!type.IsMetadataReference) { return(type.GetGenericTypeDefinition()); } var resolvedType = type.ResolveNoThrow(); if ((object)resolvedType != null) { return(resolvedType.GetGenericTypeDefinition()); } if (type is Impl.DmdGenericInstanceTypeRef) { return(type.GetGenericTypeDefinition()); } if (type.MetadataName.LastIndexOf('`') >= 0) { return(type); } return(null); }
static void WriteAssemblyFullName(StringBuilder sb, DmdType type) { if (!type.IsMetadataReference) { if (type.TypeSignatureKind != DmdTypeSignatureKind.GenericInstance) { type.Assembly.GetName().FormatFullNameTo(sb); return; } // Won't throw type = type.GetGenericTypeDefinition(); } var nonNested = Impl.DmdTypeUtilities.GetNonNestedType(type); if ((object)nonNested != null) { var typeScope = nonNested.TypeScope; switch (typeScope.Kind) { default: case DmdTypeScopeKind.Invalid: sb.Append("???"); return; case DmdTypeScopeKind.Module: ((DmdModule)typeScope.Data).Assembly.GetName().FormatFullNameTo(sb); return; case DmdTypeScopeKind.ModuleRef: ((IDmdAssemblyName)typeScope.Data2).FormatFullNameTo(sb); return; case DmdTypeScopeKind.AssemblyRef: ((IDmdAssemblyName)typeScope.Data).FormatFullNameTo(sb); return; } } }
/// <summary> /// Gets the hash code of a type /// </summary> /// <param name="a">Type</param> /// <returns></returns> public int GetHashCode(DmdType a) { if ((object)a == null) { return(0); } if (!IncrementRecursionCounter()) { return(0); } int hc = CompareCustomModifiers ? GetHashCode(a.GetCustomModifiers()) : 0; switch (a.TypeSignatureKind) { case DmdTypeSignatureKind.Type: hc ^= (object)a.DeclaringType == null ? HASHCODE_MAGIC_TYPE : HASHCODE_MAGIC_NESTED_TYPE; hc ^= MemberNameGetHashCode(a.MetadataName); hc ^= MemberNameGetHashCode(a.MetadataNamespace); hc ^= GetHashCode(a.DeclaringType); // Don't include the type scope in the hash since it can be one of Module, ModuleRef, AssemblyRef // and we could only hash the common denominator which isn't much at all. break; case DmdTypeSignatureKind.Pointer: hc ^= HASHCODE_MAGIC_ET_PTR ^ GetHashCode(a.GetElementType()); break; case DmdTypeSignatureKind.ByRef: hc ^= HASHCODE_MAGIC_ET_BYREF ^ GetHashCode(a.GetElementType()); break; case DmdTypeSignatureKind.SZArray: hc ^= HASHCODE_MAGIC_ET_SZARRAY ^ GetHashCode(a.GetElementType()); break; case DmdTypeSignatureKind.TypeGenericParameter: hc ^= HASHCODE_MAGIC_ET_VAR ^ a.GenericParameterPosition; if (CompareGenericParameterDeclaringMember) { hc ^= GetHashCode(a.DeclaringType); } break; case DmdTypeSignatureKind.MethodGenericParameter: hc ^= HASHCODE_MAGIC_ET_MVAR ^ a.GenericParameterPosition; if (CompareGenericParameterDeclaringMember) { options &= ~DmdSigComparerOptions.CompareGenericParameterDeclaringMember; hc ^= GetHashCode(a.DeclaringMethod); options |= DmdSigComparerOptions.CompareGenericParameterDeclaringMember; } break; case DmdTypeSignatureKind.MDArray: hc ^= HASHCODE_MAGIC_ET_ARRAY; hc ^= a.GetArrayRank(); if (!IgnoreMultiDimensionalArrayLowerBoundsAndSizes) { hc ^= GetHashCode(a.GetArraySizes()); hc ^= GetHashCode(a.GetArrayLowerBounds()); } hc ^= GetHashCode(a.GetElementType()); break; case DmdTypeSignatureKind.GenericInstance: hc ^= HASHCODE_MAGIC_ET_GENERICINST; hc ^= GetHashCode(a.GetGenericTypeDefinition()); hc ^= GetHashCode(a.GetGenericArguments()); break; case DmdTypeSignatureKind.FunctionPointer: hc ^= HASHCODE_MAGIC_ET_FNPTR; hc ^= GetHashCode(a.GetFunctionPointerMethodSignature()); break; default: throw new InvalidOperationException(); } DecrementRecursionCounter(); return(hc); }
/// <summary> /// Compares two types /// </summary> /// <param name="a">First type</param> /// <param name="b">Second type</param> /// <returns></returns> public bool Equals(DmdType a, DmdType b) { if ((object)a == b) { return(true); } if ((object)a == null || (object)b == null) { return(false); } if (!IncrementRecursionCounter()) { return(false); } bool result; var at = a.TypeSignatureKind; if (at != b.TypeSignatureKind) { result = false; } else if (CompareCustomModifiers && !Equals(a.GetCustomModifiers(), b.GetCustomModifiers())) { result = false; } else { switch (at) { case DmdTypeSignatureKind.Type: result = MemberNameEquals(a.MetadataName, b.MetadataName) && MemberNameEquals(a.MetadataNamespace, b.MetadataNamespace) && Equals(a.DeclaringType, b.DeclaringType); // Type scope only needs to be checked if it's a non-nested type if (result && !DontCompareTypeScope && (object)a.DeclaringType == null) { result = TypeScopeEquals(a, b); if (!result) { // One or both of the types could be exported types. We need to // resolve them and then compare again. var ra = a.ResolveNoThrow(); var rb = (object)ra == null ? null : b.ResolveNoThrow(); result = (object)ra != null && (object)rb != null && TypeScopeEquals(ra, rb); if (!result && CheckTypeEquivalence) { result = TIAHelper.Equivalent(ra, rb); } } } break; case DmdTypeSignatureKind.Pointer: case DmdTypeSignatureKind.ByRef: case DmdTypeSignatureKind.SZArray: result = Equals(a.GetElementType(), b.GetElementType()); break; case DmdTypeSignatureKind.TypeGenericParameter: result = a.GenericParameterPosition == b.GenericParameterPosition; if (result && CompareGenericParameterDeclaringMember) { result = Equals(a.DeclaringType, b.DeclaringType); } break; case DmdTypeSignatureKind.MethodGenericParameter: result = a.GenericParameterPosition == b.GenericParameterPosition; if (result && CompareGenericParameterDeclaringMember) { options &= ~DmdSigComparerOptions.CompareGenericParameterDeclaringMember; result = Equals(a.DeclaringMethod, b.DeclaringMethod); options |= DmdSigComparerOptions.CompareGenericParameterDeclaringMember; } break; case DmdTypeSignatureKind.MDArray: result = a.GetArrayRank() == b.GetArrayRank() && (IgnoreMultiDimensionalArrayLowerBoundsAndSizes || (Equals(a.GetArraySizes(), b.GetArraySizes()) && Equals(a.GetArrayLowerBounds(), b.GetArrayLowerBounds()))) && Equals(a.GetElementType(), b.GetElementType()); break; case DmdTypeSignatureKind.GenericInstance: result = Equals(a.GetGenericTypeDefinition(), b.GetGenericTypeDefinition()) && Equals(a.GetGenericArguments(), b.GetGenericArguments()); break; case DmdTypeSignatureKind.FunctionPointer: result = Equals(a.GetFunctionPointerMethodSignature(), b.GetFunctionPointerMethodSignature()); break; default: throw new InvalidOperationException(); } } DecrementRecursionCounter(); return(result); }