We currently have a small behavior hole on Windows where if a binary uses TypeEquivalence, it is technically possible to get crossgen2 to generate invalid code.
This fixes that by adding support for type equivalence to the managed type system, and adjusting crossgen2 to use it. This is complicated by the detail that this may generate some type references which cannot be referenced from an R2R file, so additional error checking was needed (this additional error checking is what fixes #67855).
However, while basic support for type equivalence has been added to the type system, support for actually performing type equivalent interface resolution has not been, so devirtualization of type equivalent interface calls is disabled. At this time, I do not expect to see a customer need for implementing that fairly complicated feature
Fixes #67855
CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_IMPL_NOT_REFERENCEABLE, // object class cannot be referenced from R2R code due to missing tokens
CORINFO_DEVIRTUALIZATION_FAILED_DUPLICATE_INTERFACE, // crossgen2 virtual method algorithm and runtime algorithm differ in the presence of duplicate interface implementations
CORINFO_DEVIRTUALIZATION_FAILED_DECL_NOT_REPRESENTABLE, // Decl method cannot be represented in R2R image
+ CORINFO_DEVIRTUALIZATION_FAILED_TYPE_EQUIVALENCE, // Support for type equivalence in devirtualization is not yet implemented in crossgen2
CORINFO_DEVIRTUALIZATION_COUNT, // sentinel for maximum value
};
#define GUID_DEFINED
#endif // !GUID_DEFINED
-constexpr GUID JITEEVersionIdentifier = { /* 2335da47-1d6c-4844-96b6-025558a525ba */
- 0x2335da47,
- 0x1d6c,
- 0x4844,
- {0x96, 0xb6, 0x02, 0x55, 0x58, 0xa5, 0x25, 0xba}
+constexpr GUID JITEEVersionIdentifier = { /* ba2c087c-9b8b-49c1-a52f-3514eb489308 */
+ 0xba2c087c,
+ 0x9b8b,
+ 0x49c1,
+ {0xa5, 0x2f, 0x35, 0x14, 0xeb, 0x48, 0x93, 0x08}
};
-
+
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// END JITEEVersionIdentifier
"interface implementations";
case CORINFO_DEVIRTUALIZATION_FAILED_DECL_NOT_REPRESENTABLE:
return "Decl method cannot be represented in R2R image";
+ case CORINFO_DEVIRTUALIZATION_FAILED_TYPE_EQUIVALENCE:
+ return "Support for type equivalence in devirtualization is not yet implemented in crossgen2";
default:
return "undefined";
}
private static TypeDesc EnsureLoadableTypeUncached(TypeDesc type)
{
+ if (type.TypeIdentifierData != null)
+ {
+ if (!type.TypeHasCharacteristicsRequiredToBeLoadableTypeEquivalentType)
+ {
+ ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
+ }
+ }
+
if (type.IsParameterizedType)
{
// Validate parameterized types
bDepth--;
}
- while (ta != tb)
+ while (!ta.IsEquivalentTo(tb))
{
ta = ta.BaseType;
tb = tb.BaseType;
Debug.Assert(taElem != tbElem);
TypeDesc mergeElem;
- if (taElem.IsArray && tbElem.IsArray)
+ if (taElem.IsEquivalentTo(tbElem))
+ {
+ mergeElem = taElem;
+ }
+ else if (taElem.IsArray && tbElem.IsArray)
{
mergeElem = MergeArrayTypesToCommonParent((ArrayType)taElem, (ArrayType)tbElem);
}
sig->_retType = (byte)corInfoRetType;
sig->retTypeSigClass = ObjectToHandle(signature.ReturnType);
+#if READYTORUN
+ ValidateSafetyOfUsingTypeEquivalenceOfType(signature.ReturnType);
+#endif
+
sig->flags = 0; // used by IL stubs code
sig->numArgs = (ushort)signature.Length;
ModuleToken methodModuleToken = HandleToModuleToken(ref pResolvedToken);
var resolver = _compilation.NodeFactory.Resolver;
resolver.AddModuleTokenForMethod(method, methodModuleToken);
+ ValidateSafetyOfUsingTypeEquivalenceInSignature(method.Signature);
}
#else
_compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(ref _additionalDependencies, _compilation.NodeFactory, (MethodIL)methodIL, method);
#if !READYTORUN
_compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(ref _additionalDependencies, _compilation.NodeFactory, (MethodIL)methodIL, field);
+#else
+ ValidateSafetyOfUsingTypeEquivalenceOfType(field.FieldType);
#endif
}
else
CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_IMPL_NOT_REFERENCEABLE, // object class cannot be referenced from R2R code due to missing tokens
CORINFO_DEVIRTUALIZATION_FAILED_DUPLICATE_INTERFACE, // crossgen2 virtual method algorithm and runtime algorithm differ in the presence of duplicate interface implementations
CORINFO_DEVIRTUALIZATION_FAILED_DECL_NOT_REPRESENTABLE, // Decl method cannot be represented in R2R image
+ CORINFO_DEVIRTUALIZATION_FAILED_TYPE_EQUIVALENCE, // Support for type equivalence in devirtualization is not yet implemented in crossgen2
CORINFO_DEVIRTUALIZATION_COUNT, // sentinel for maximum value
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Debug = System.Diagnostics.Debug;
+using System.Collections.Generic;
+using Internal.TypeSystem.Ecma;
+
+namespace Internal.TypeSystem
+{
+ public static partial class CastingHelper
+ {
+ static partial void IsEquivalentTo(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect visited, ref bool isEquivalentTo)
+ {
+ isEquivalentTo = IsEquivalentToHelper(thisType, otherType, visited);
+ return;
+ }
+
+ private static bool IsEquivalentToHelper(TypeDesc thisType, TypeDesc otherType, StackOverflowProtect visited)
+ {
+ if (thisType == otherType)
+ return true;
+
+ if (thisType.Category != otherType.Category)
+ return false;
+
+ switch (thisType.Category)
+ {
+ case TypeFlags.SignatureTypeVariable:
+ case TypeFlags.SignatureMethodVariable:
+ case TypeFlags.GenericParameter:
+ return false;
+
+ case TypeFlags.Array:
+ var arrayType = (ArrayType)thisType;
+ var otherArrayType = (ArrayType)otherType;
+ if (arrayType.Rank != otherArrayType.Rank)
+ return false;
+ return arrayType.ParameterType.IsEquivalentTo(otherArrayType.ParameterType, visited);
+
+ case TypeFlags.SzArray:
+ case TypeFlags.ByRef:
+ case TypeFlags.Pointer:
+ return ((ParameterizedType)thisType).ParameterType.IsEquivalentTo(((ParameterizedType)otherType).ParameterType, visited);
+
+ case TypeFlags.FunctionPointer:
+ return false;
+
+ default:
+ Debug.Assert(thisType.IsDefType);
+ if (!thisType.IsTypeDefEquivalent || !otherType.IsTypeDefEquivalent)
+ {
+ if (thisType.HasInstantiation && otherType.HasInstantiation)
+ {
+ // We might be in the generic interface case
+ }
+ else
+ {
+ return false;
+ }
+ }
+ return ((DefType)thisType).IsEquivalentToDefType((DefType)otherType, visited);
+ }
+ }
+
+ private static bool IsEquivalentToDefType(this DefType thisType, DefType otherType, StackOverflowProtect visited)
+ {
+ if (thisType.HasInstantiation)
+ {
+ // Limit equivalence on generics only to interfaces
+ if (!thisType.IsInterface || !otherType.IsInterface)
+ {
+ return false;
+ }
+
+ if (thisType.Instantiation.Length != otherType.Instantiation.Length)
+ {
+ return false;
+ }
+
+ // Generic equivalence only allows the instantiation to be non-equal
+ if (!thisType.HasSameTypeDefinition(otherType))
+ return false;
+
+ for (int i = 0; i < thisType.Instantiation.Length; i++)
+ {
+ if (!thisType.Instantiation[i].IsEquivalentTo(otherType.Instantiation[i], visited))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return IsEquivalentTo_TypeDefinition((MetadataType)thisType.GetTypeDefinition(), (MetadataType)otherType.GetTypeDefinition(), visited);
+
+ static bool IsEquivalentTo_TypeDefinition(MetadataType type1, MetadataType type2, StackOverflowProtect visited)
+ {
+ Debug.Assert(type1.GetTypeDefinition() == type1);
+ Debug.Assert(type2.GetTypeDefinition() == type2);
+
+ var stackOverflowProtectKey = new CastingPair(type1, type2);
+ if (visited != null)
+ {
+ if (visited.Contains(stackOverflowProtectKey))
+ {
+ // we are in the process of comparing these tokens already. Assume success
+ return true;
+ }
+ }
+
+ StackOverflowProtect protect = new StackOverflowProtect(stackOverflowProtectKey, visited);
+
+ TypeIdentifierData data1 = type1.TypeIdentifierData;
+ TypeIdentifierData data2 = type2.TypeIdentifierData;
+ if (data1 == null || data2 == null)
+ {
+ return false;
+ }
+
+ // Check to ensure that the types are actually opted into equivalence
+ if (!type1.IsTypeDefEquivalent || !type2.IsTypeDefEquivalent)
+ return false;
+
+ if (!data1.Equals(data2))
+ return false;
+
+ if (type1.Name != type2.Name)
+ return false;
+
+ if (type1.Namespace != type2.Namespace)
+ return false;
+
+ var containingType1 = (MetadataType)type1.ContainingType;
+ var containingType2 = (MetadataType)type2.ContainingType;
+
+ // Types must be either not nested, or nested in equivalent types
+ if ((containingType1 == null) != (containingType2 == null))
+ {
+ return false;
+ }
+
+ if ((containingType1 != null) && !IsEquivalentTo_TypeDefinition(containingType1, containingType2, visited))
+ {
+ return false;
+ }
+
+ if (type1.IsInterface != type2.IsInterface)
+ {
+ return false;
+ }
+ if (type1.IsInterface)
+ {
+ return true;
+ }
+ if ((type1.IsEnum != type2.IsEnum) || (type1.IsValueType != type2.IsValueType))
+ {
+ return false;
+ }
+
+ if (type1.IsEnum)
+ {
+ return CompareStructuresForEquivalence(type1, type2, visited, enumMode: true);
+ }
+ else if (type1.IsValueType)
+ {
+ return CompareStructuresForEquivalence(type1, type2, visited, enumMode: false);
+ }
+ else if ((type1.IsDelegate == type2.IsDelegate) && type1.IsDelegate)
+ {
+ return CompareDelegatesForEquivalence(type1, type2, visited);
+ }
+
+ return false;
+ }
+
+ static bool CompareDelegatesForEquivalence(MetadataType type1, MetadataType type2, StackOverflowProtect visited)
+ {
+ var invoke1 = type1.GetMethod("Invoke", null);
+ var invoke2 = type2.GetMethod("Invoke", null);
+
+ if (invoke1 == null)
+ return false;
+
+ if (invoke2 == null)
+ return false;
+
+ return invoke1.Signature.EquivalentTo(invoke2.Signature, visited);
+ }
+
+ static bool CompareStructuresForEquivalence(MetadataType type1, MetadataType type2, StackOverflowProtect visited, bool enumMode)
+ {
+ foreach (var method in type1.GetMethods())
+ {
+ // If there are any methods, then it isn't actually a type-equivalent type
+ return false;
+ }
+
+ foreach (var method in type2.GetMethods())
+ {
+ // If there are any methods, then it isn't actually a type-equivalent type
+ return false;
+ }
+
+ // Compare field types for equivalence
+ var fields1 = type1.GetFields().GetEnumerator();
+ var fields2 = type2.GetFields().GetEnumerator();
+
+ while (true)
+ {
+ bool nonTypeEquivalentValidFieldFound;
+
+ FieldDesc field1 = GetNextTypeEquivalentField(fields1, enumMode, out nonTypeEquivalentValidFieldFound);
+ if (nonTypeEquivalentValidFieldFound)
+ return false;
+ FieldDesc field2 = GetNextTypeEquivalentField(fields2, enumMode, out nonTypeEquivalentValidFieldFound);
+ if (nonTypeEquivalentValidFieldFound)
+ return false;
+
+ if ((field1 == null) && (field2 == null))
+ {
+ // We ran out of fields on both types before finding a failure
+ break;
+ }
+
+ if ((field1 == null) || (field2 == null))
+ {
+ // we ran out of fields on 1 type.
+ return false;
+ }
+
+ // Compare the field signatures for equivalence
+ // TODO: Technically this comparison should include custom modifiers on the field signatures
+ if (!field1.FieldType.IsEquivalentTo(field2.FieldType, visited))
+ {
+ return false;
+ }
+
+ // Compare the field marshal details
+ var marshalAsDescriptor1 = field1.GetMarshalAsDescriptor();
+ var marshalAsDescriptor2 = field2.GetMarshalAsDescriptor();
+
+ if (marshalAsDescriptor1 == null || marshalAsDescriptor2 == null)
+ {
+ if (marshalAsDescriptor1 != marshalAsDescriptor2)
+ return false;
+ }
+ else if (!marshalAsDescriptor1.Equals(marshalAsDescriptor2))
+ {
+ return false;
+ }
+ }
+
+ // At this point we know that the set of fields is the same, and have the same types
+ if (!enumMode)
+ {
+ if (!CompareTypeLayout(type1, type2))
+ {
+ return false;
+ }
+ }
+ return true;
+
+ static bool CompareTypeLayout(MetadataType type1, MetadataType type2)
+ {
+ // Types must either be Sequential or Explicit layout
+ if (type1.IsSequentialLayout != type2.IsSequentialLayout)
+ {
+ return false;
+ }
+
+ if (type1.IsExplicitLayout != type2.IsExplicitLayout)
+ {
+ return false;
+ }
+
+ if (!(type1.IsSequentialLayout || type1.IsExplicitLayout))
+ {
+ return false;
+ }
+
+ bool explicitLayout = type1.IsExplicitLayout;
+
+ // they must have the same charset
+ if (type1.PInvokeStringFormat != type2.PInvokeStringFormat)
+ {
+ return false;
+ }
+
+ var layoutMetadata1 = type1.GetClassLayout();
+ var layoutMetadata2 = type2.GetClassLayout();
+ if ((layoutMetadata1.PackingSize != layoutMetadata2.PackingSize) ||
+ (layoutMetadata1.Size != layoutMetadata2.Size))
+ return false;
+
+ if ((explicitLayout) && !(layoutMetadata1.Offsets == null && layoutMetadata2.Offsets == null))
+ {
+ if (layoutMetadata1.Offsets == null)
+ return false;
+
+ if (layoutMetadata2.Offsets == null)
+ return false;
+
+ for (int index = 0; index < layoutMetadata1.Offsets.Length; index++)
+ {
+ if (layoutMetadata1.Offsets[index].Offset != layoutMetadata2.Offsets[index].Offset)
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static FieldDesc GetNextTypeEquivalentField(IEnumerator<FieldDesc> fieldEnum, bool enumMode, out bool fieldNotValidInEquivalentTypeFound)
+ {
+ fieldNotValidInEquivalentTypeFound = false;
+ while (fieldEnum.MoveNext())
+ {
+ var field = fieldEnum.Current;
+
+ if (field.GetAttributeEffectiveVisibility() == EffectiveVisibility.Public && !field.IsStatic)
+ return field;
+
+ // Only public instance fields, and literal fields on enums are permitted in type equivalent structures
+ if (!enumMode || !field.IsLiteral)
+ {
+ fieldNotValidInEquivalentTypeFound = true;
+ return null;
+ }
+ }
+ return null;
+ }
+ }
+ }
+ }
+}
/// </summary>
public static bool IsCompatibleWith(this TypeDesc thisType, TypeDesc otherType)
{
+ return thisType.IsCompatibleWith(otherType, null);
+ }
+
+ internal static bool IsCompatibleWith(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect visited)
+ {
// Structs can be cast to the interfaces they implement, but they are not compatible according to ECMA I.8.7.1
bool isCastFromValueTypeToReferenceType = otherType.IsValueType && !thisType.IsValueType;
if (isCastFromValueTypeToReferenceType)
}
// Nullable<T> can be cast to T, but this is not compatible according to ECMA I.8.7.1
- bool isCastFromNullableOfTtoT = thisType.IsNullable && otherType.IsEquivalentTo(thisType.Instantiation[0]);
+ bool isCastFromNullableOfTtoT = thisType.IsNullable && otherType.IsEquivalentTo(thisType.Instantiation[0], visited);
if (isCastFromNullableOfTtoT)
{
return false;
return otherType.CanCastTo(thisType);
}
- private static bool IsEquivalentTo(this TypeDesc thisType, TypeDesc otherType)
+ public static bool IsEquivalentTo(this TypeDesc thisType, TypeDesc otherType)
{
- // TODO: Once type equivalence is implemented, this implementation needs to be enhanced to honor it.
- return thisType == otherType;
+ bool isEquivalentTo = thisType == otherType;
+ if (!isEquivalentTo)
+ thisType.IsEquivalentTo(otherType, (StackOverflowProtect)null, ref isEquivalentTo);
+
+ return isEquivalentTo;
}
+ internal static bool IsEquivalentTo(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect visited)
+ {
+ bool isEquivalentTo = thisType == otherType;
+ if (!isEquivalentTo)
+ thisType.IsEquivalentTo(otherType, visited, ref isEquivalentTo);
+
+ return isEquivalentTo;
+ }
+
+ static partial void IsEquivalentTo(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect visited, ref bool isEquivalentTo);
private static bool CanCastToInternal(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
{
if (thisType == otherType)
// unboxed versions do not. Parameterized types have the
// unboxed version, thus, if the from type parameter is value
// class then only an exact match/equivalence works.
- if (thisType.ParameterType == paramType)
+ if (thisType.ParameterType.IsEquivalentTo(paramType))
{
return true;
}
private static bool CanCastToNonVariantInterface(this TypeDesc thisType, TypeDesc otherType)
{
- if (otherType == thisType)
+ if (otherType.IsEquivalentTo(thisType))
{
return true;
}
foreach (var interfaceType in thisType.RuntimeInterfaces)
{
- if (interfaceType == otherType)
+ if (interfaceType.IsEquivalentTo(otherType))
{
return true;
}
private static bool CanCastByVarianceToInterfaceOrDelegate(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protectInput)
{
+ if (thisType == otherType)
+ {
+ return true;
+ }
+
if (!thisType.HasSameTypeDefinition(otherType))
{
return false;
TypeDesc arg = instantiationThis[i];
TypeDesc targetArg = instantiationTarget[i];
- if (arg != targetArg)
+ if (!arg.IsEquivalentTo(targetArg))
{
GenericParameterDesc openArgType = (GenericParameterDesc)instantiationOpen[i];
// First chase inheritance hierarchy until we hit a class that only differs in its instantiation
do
{
- if (curType == otherType)
+ if (curType.IsEquivalentTo(otherType))
{
return true;
}
do
{
- if (curType == otherType)
+ if (curType.IsEquivalentTo(otherType))
return true;
curType = curType.BaseType;
return false;
}
+ }
- private sealed class StackOverflowProtect
- {
- private CastingPair _value;
- private StackOverflowProtect _previous;
-
- public StackOverflowProtect(CastingPair value, StackOverflowProtect previous)
- {
- _value = value;
- _previous = previous;
- }
+ internal sealed class StackOverflowProtect
+ {
+ private CastingPair _value;
+ private StackOverflowProtect _previous;
- public bool Contains(CastingPair value)
- {
- for (var current = this; current != null; current = current._previous)
- if (current._value.Equals(value))
- return true;
- return false;
- }
+ public StackOverflowProtect(CastingPair value, StackOverflowProtect previous)
+ {
+ _value = value;
+ _previous = previous;
}
- private struct CastingPair
+ public static StackOverflowProtect GetTypeEquivalentForbiddenScope(StackOverflowProtect previous)
{
- public readonly TypeDesc FromType;
- public readonly TypeDesc ToType;
+ var protect = new StackOverflowProtect(default(CastingPair), previous);
+ return protect;
+ }
- public CastingPair(TypeDesc fromType, TypeDesc toType)
+ public bool Contains(CastingPair value)
+ {
+ for (var current = this; current != null; current = current._previous)
{
- FromType = fromType;
- ToType = toType;
+ if (current._value.Equals(value))
+ return true;
}
+ return false;
+ }
+ }
- public bool Equals(CastingPair other) => FromType == other.FromType && ToType == other.ToType;
+ internal struct CastingPair
+ {
+ public readonly TypeDesc FromType;
+ public readonly TypeDesc ToType;
+
+ public CastingPair(TypeDesc fromType, TypeDesc toType)
+ {
+ FromType = fromType;
+ ToType = toType;
}
+
+ public bool Equals(CastingPair other) => FromType == other.FromType && ToType == other.ToType;
}
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Internal.TypeSystem
+{
+ public partial class InstantiatedType
+ {
+ public override TypeIdentifierData TypeIdentifierData => _typeDef.TypeIdentifierData;
+ public override bool IsWindowsRuntime => _typeDef.IsWindowsRuntime;
+
+ }
+}
return _typeDef.Context.GetMethodForInstantiatedType(typicalMethodDef, this);
}
+ public override MethodDesc GetMethodWithEquivalentSignature(string name, MethodSignature signature, Instantiation substitution)
+ {
+ MethodDesc typicalMethodDef = _typeDef.GetMethodWithEquivalentSignature(name, signature, substitution);
+ if (typicalMethodDef == null)
+ return null;
+ return _typeDef.Context.GetMethodForInstantiatedType(typicalMethodDef, this);
+ }
+
public override MethodDesc GetStaticConstructor()
{
MethodDesc typicalCctor = _typeDef.GetStaticConstructor();
/// <summary>
/// Find matching a matching method by name and sig on a type. (Restricted to virtual methods only)
+ /// This will find both exact and equivalent matches, but will prefer exact matches.
/// </summary>
/// <param name="targetMethod"></param>
/// <param name="currentType"></param>
MethodSignature sig = targetMethod.Signature;
MethodDesc implMethod = null;
+ MethodDesc implMethodEquivalent = null;
foreach (MethodDesc candidate in currentType.GetAllVirtualMethods())
{
if (candidate.Name == name)
{
- if (candidate.Signature.Equals(sig))
+ if (candidate.Signature.EquivalentTo(sig))
{
if (nameSigMatchMethodIsValidCandidate == null || nameSigMatchMethodIsValidCandidate(targetMethod, candidate))
{
- implMethod = candidate;
+ implMethodEquivalent = candidate;
+
+ if (candidate.Signature.Equals(sig))
+ implMethod = candidate;
// If reverseMethodSearch is enabled, we want to find the last match on this type, not the first
// (reverseMethodSearch is used for most matches except for searches for name/sig method matches for interface methods on the most derived type)
- if (!reverseMethodSearch)
+ if (!reverseMethodSearch && implMethod != null)
return implMethod;
}
}
}
}
+ if (implMethod == null)
+ return implMethodEquivalent;
+
return implMethod;
}
if (unificationGroup.RequiresSlotUnification(declSlot) || implSlot.RequiresSlotUnification())
{
- if (implSlot.Signature.EqualsWithCovariantReturnType(unificationGroup.DefiningMethod.Signature))
+ if (implSlot.Signature.EquivalentWithCovariantReturnType(unificationGroup.DefiningMethod.Signature))
{
unificationGroup.AddMethodRequiringSlotUnification(declSlot);
unificationGroup.AddMethodRequiringSlotUnification(implSlot);
FindBaseUnificationGroup(baseType, addDeclGroup);
Debug.Assert(
addDeclGroup.IsInGroupOrIsDefiningSlot(declSlot) ||
- (addDeclGroup.RequiresSlotUnification(declSlot) && addDeclGroup.DefiningMethod.Signature.EqualsWithCovariantReturnType(declSlot.Signature)));
+ (addDeclGroup.RequiresSlotUnification(declSlot) && addDeclGroup.DefiningMethod.Signature.EquivalentWithCovariantReturnType(declSlot.Signature)));
foreach (MethodDesc methodImplRequiredToRemainInEffect in addDeclGroup.MethodsRequiringSlotUnification)
{
}
else if (unificationGroup.RequiresSlotUnification(declSlot))
{
- if (implSlot.Signature.EqualsWithCovariantReturnType(unificationGroup.DefiningMethod.Signature))
+ if (implSlot.Signature.EquivalentWithCovariantReturnType(unificationGroup.DefiningMethod.Signature))
{
unificationGroup.AddMethodRequiringSlotUnification(implSlot);
unificationGroup.SetDefiningMethod(implSlot);
public bool Equals(MethodSignature otherSignature)
{
- return Equals(otherSignature, allowCovariantReturn: false);
+ return Equals(otherSignature, allowCovariantReturn: false, allowEquivalence: false);
}
- public bool EqualsWithCovariantReturnType(MethodSignature otherSignature)
+ public bool EquivalentWithCovariantReturnType(MethodSignature otherSignature)
{
- return Equals(otherSignature, allowCovariantReturn: true);
+ return Equals(otherSignature, allowCovariantReturn: true, allowEquivalence: true);
}
- private bool Equals(MethodSignature otherSignature, bool allowCovariantReturn)
+ public bool EquivalentTo(MethodSignature otherSignature)
+ {
+ return Equals(otherSignature, allowCovariantReturn: false, allowEquivalence: true, visited: null);
+ }
+
+ internal bool EquivalentTo(MethodSignature otherSignature, StackOverflowProtect visited)
+ {
+ return Equals(otherSignature, allowCovariantReturn: false, allowEquivalence: true, visited: visited);
+ }
+
+ private bool Equals(MethodSignature otherSignature, bool allowCovariantReturn, bool allowEquivalence, StackOverflowProtect visited = null)
{
if (this._flags != otherSignature._flags)
return false;
if (this._genericParameterCount != otherSignature._genericParameterCount)
return false;
- if (this._returnType != otherSignature._returnType)
+ if (!IsTypeEqualHelper(this._returnType, otherSignature._returnType, allowEquivalence, visited))
{
if (!allowCovariantReturn)
return false;
- if (!otherSignature._returnType.IsCompatibleWith(this._returnType))
+ if (!otherSignature._returnType.IsCompatibleWith(this._returnType, visited))
return false;
}
for (int i = 0; i < this._parameters.Length; i++)
{
- if (this._parameters[i] != otherSignature._parameters[i])
+ if (!IsTypeEqualHelper(this._parameters[i], otherSignature._parameters[i], allowEquivalence, visited))
return false;
}
if (thisData.index != otherData.index ||
thisData.kind != otherData.kind ||
- thisData.type != otherData.type)
+ !IsTypeEqualHelper(thisData.type, otherData.type, allowEquivalence, visited))
{
return false;
}
}
return false;
+
+ static bool IsTypeEqualHelper(TypeDesc type1, TypeDesc type2, bool allowEquivalence, StackOverflowProtect visited)
+ {
+ if (type1 == type2)
+ return true;
+
+ if (allowEquivalence)
+ {
+ if (type1.IsEquivalentTo(type2, visited))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
}
public override bool Equals(object obj)
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Debug = System.Diagnostics.Debug;
+using System;
+
+namespace Internal.TypeSystem
+{
+ public class TypeIdentifierData : IEquatable<TypeIdentifierData>
+ {
+ public TypeIdentifierData(string scope, string name)
+ {
+ Debug.Assert(scope != null);
+ Debug.Assert(name != null);
+ Scope = scope;
+ Name = name;
+ }
+
+ public static readonly TypeIdentifierData Empty = new TypeIdentifierData("", "");
+
+ public string Scope { get; }
+ public string Name { get; }
+
+ public bool Equals(TypeIdentifierData other)
+ {
+ if (Scope != other.Scope)
+ return false;
+ return Name == other.Name;
+ }
+
+ public override int GetHashCode()
+ {
+ return Scope.GetHashCode() ^ Name.GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o is TypeIdentifierData other)
+ return Equals(other);
+ return false;
+ }
+ }
+
+ public partial class TypeDesc
+ {
+ public virtual TypeIdentifierData TypeIdentifierData => null;
+
+ public bool IsTypeDefEquivalent => TypeIdentifierData != null;
+
+ public bool HasTypeEquivalence
+ {
+ get
+ {
+ if (!Context.SupportsTypeEquivalence)
+ return false;
+ if (IsTypeDefEquivalent)
+ return true;
+ if (HasInstantiation)
+ {
+ foreach (var type in Instantiation)
+ {
+ if (type.HasTypeEquivalence)
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public virtual bool IsWindowsRuntime => false;
+
+ public virtual bool IsComImport => false;
+
+ public virtual bool IsComEventInterface => false;
+
+ public bool TypeHasCharacteristicsRequiredToBeTypeEquivalent
+ {
+ get
+ {
+ if (this is not DefType)
+ return false;
+
+ var defType = (DefType)this;
+
+ // 1. Type is a COMImport/COMEvent interface, enum, struct, or delegate
+ if (!(IsInterface && (IsComImport || IsComEventInterface)) && !IsValueType && !IsDelegate)
+ return false;
+
+ // 2. Type is not generic
+ if (HasInstantiation)
+ return false;
+
+ // 3. Type is externally visible (i.e public)
+ if (!((TypeDesc)defType).GetEffectiveVisibility().IsExposedOutsideOfThisAssembly(false))
+ return false;
+
+ // 4. Type is not tdWindowsRuntime
+ if (IsWindowsRuntime)
+ return false;
+
+ var containingType = defType.ContainingType;
+ if (defType.ContainingType != null)
+ {
+ if (containingType.TypeIdentifierData == null)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ // A type may be type equivalent for the purposes of signature comparison, but not permitted
+ // to actually be loaded. This predicate checks for the loadability with regards
+ // to type equivalence rules for types that have a TypeIdentifierData
+ public bool TypeHasCharacteristicsRequiredToBeLoadableTypeEquivalentType
+ {
+ get
+ {
+ // There is a set of checks that must be passed to be eligible implicitly for
+ // type equivalence. We need to pass these checks for explicitly type equivalent
+ // types as well.
+ if (!TypeHasCharacteristicsRequiredToBeTypeEquivalent)
+ return false;
+
+ // A type equivalent structure type MUST not have any non-static methods
+ if (IsValueType)
+ {
+ foreach (var method in GetMethods())
+ {
+ // Note that while a type equivalent structure MAY have static methods, if it does so it will never compare as
+ // equivalent to another type. This is an odd quirk, but seems to be consistent in the runtime since the feature was built.
+ if (!method.Signature.IsStatic)
+ return false;
+ }
+
+ foreach (var field in GetFields())
+ {
+ if (field.IsLiteral)
+ {
+ // Literal fields are ok
+ continue;
+ }
+
+ if (field.IsStatic)
+ {
+ return false;
+ }
+
+ if (field.GetEffectiveVisibility() != EffectiveVisibility.Public)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+}
return null;
}
+ public virtual MethodDesc GetMethodWithEquivalentSignature(string name, MethodSignature signature, Instantiation substitution)
+ {
+ foreach (var method in GetMethods())
+ {
+ if (method.Name == name)
+ {
+ if (signature == null || signature.EquivalentTo(method.Signature.ApplySubstitution(substitution)))
+ return method;
+ }
+ }
+ return null;
+ }
+
/// <summary>
/// Retrieves the class constructor method of this type.
/// </summary>
/// Determine if the type implements <code>IDynamicInterfaceCastable</code>
/// </summary>
protected internal abstract bool IsIDynamicInterfaceCastableInterface(DefType type);
+
+ public virtual bool SupportsTypeEquivalence => false;
+ public virtual bool SupportsCOMInterop => false;
}
}
do
{
MethodDesc method = typeDescToInspect.GetMethod(name, sig, substitution);
+ if (method == null && Context.SupportsTypeEquivalence)
+ method = typeDescToInspect.GetMethodWithEquivalentSignature(name, sig, substitution);
if (method != null)
{
// If this resolved to one of the base types, make sure it's not a constructor.
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Threading;
+
+namespace Internal.TypeSystem.Ecma
+{
+ public partial class EcmaType
+ {
+ private TypeIdentifierData _data;
+
+ private TypeIdentifierData ComputeTypeIdentifierFromGuids()
+ {
+ CustomAttributeValue<TypeDesc>? guidAttribute;
+ if (IsInterface && _typeDefinition.Attributes.HasFlag(TypeAttributes.Import))
+ {
+ // ComImport interfaces get scope from their GUID
+ guidAttribute = this.GetDecodedCustomAttribute("System.Runtime.InteropServices", "GuidAttribute");
+ }
+ else
+ {
+ // other equivalent types get it from the declaring assembly
+ var attributeHandle = this.MetadataReader.GetCustomAttributeHandle(MetadataReader.GetAssemblyDefinition().GetCustomAttributes(), "System.Runtime.InteropServices", "GuidAttribute");
+ if (attributeHandle.IsNil)
+ return null;
+
+ guidAttribute = this.MetadataReader.GetCustomAttribute(attributeHandle).DecodeValue(new CustomAttributeTypeProvider(this.EcmaModule));
+ }
+
+ if (!guidAttribute.HasValue)
+ return null;
+
+ if (guidAttribute.Value.FixedArguments.Length < 1)
+ return null;
+
+ if (guidAttribute.Value.FixedArguments[0].Type != Context.GetWellKnownType(WellKnownType.String))
+ return null;
+
+ string scope = (string)guidAttribute.Value.FixedArguments[0].Value;
+ string name = this.Name;
+ if (this.Namespace != null)
+ name = this.Namespace + "." + name;
+
+ return new TypeIdentifierData(scope, name);
+ }
+
+ private TypeIdentifierData ComputeTypeIdentifierData()
+ {
+ if (!Context.SupportsTypeEquivalence)
+ return null;
+
+ // Check for type identifier attribute
+ var typeIdentifierAttribute = this.GetDecodedCustomAttribute("System.Runtime.InteropServices", "TypeIdentifierAttribute");
+ if (typeIdentifierAttribute.HasValue)
+ {
+ // If the type has a type identifier attribute it is always considered to be type equivalent
+ if (typeIdentifierAttribute.Value.FixedArguments.Length == 0)
+ return ComputeTypeIdentifierFromGuids();
+
+ if (typeIdentifierAttribute.Value.FixedArguments.Length != 2)
+ return null;
+
+ if (typeIdentifierAttribute.Value.FixedArguments[0].Type != Context.GetWellKnownType(WellKnownType.String))
+ return null;
+
+ if (typeIdentifierAttribute.Value.FixedArguments[1].Type != Context.GetWellKnownType(WellKnownType.String))
+ return null;
+
+ _data = new TypeIdentifierData((string)typeIdentifierAttribute.Value.FixedArguments[0].Value, (string)typeIdentifierAttribute.Value.FixedArguments[1].Value);
+ return _data;
+ }
+ else
+ {
+ // In addition to the TypeIdentifierAttribute certain other types may also be opted in to type equivalence
+ if (Context.SupportsCOMInterop)
+ {
+ // 1. Type is within assembly marked with ImportedFromTypeLibAttribute or PrimaryInteropAssemblyAttribute
+ if (this.HasCustomAttribute("System.Runtime.InteropServices", "ImportedFromTypeLibAttribute") || this.HasCustomAttribute("System.Runtime.InteropServices", "PrimaryInteropAssemblyAttribute"))
+ {
+ // This type has a TypeIdentifier attribute if it has an appropriate shape to be considered type equivalent
+ }
+
+ if (!TypeHasCharacteristicsRequiredToBeTypeEquivalent)
+ return null;
+
+ _data = ComputeTypeIdentifierFromGuids();
+ }
+
+ return null;
+ }
+ }
+
+ public override TypeIdentifierData TypeIdentifierData
+ {
+ get
+ {
+ if (_data != null)
+ {
+ if (object.ReferenceEquals(_data, TypeIdentifierData.Empty))
+ return null;
+ return _data;
+ }
+ var data = ComputeTypeIdentifierData() ?? TypeIdentifierData.Empty;
+
+ Interlocked.CompareExchange(ref _data, data, null);
+
+ // Recurse to read from _data and return a consistent result
+ return this.TypeIdentifierData;
+ }
+ }
+
+ public override bool IsWindowsRuntime
+ {
+ get
+ {
+ return _typeDefinition.Attributes.HasFlag(TypeAttributes.WindowsRuntime);
+ }
+ }
+
+ public override bool IsComImport
+ {
+ get
+ {
+ return _typeDefinition.Attributes.HasFlag(TypeAttributes.Import);
+ }
+ }
+
+ public override bool IsComEventInterface
+ {
+ get
+ {
+ return HasCustomAttribute("System.Runtime.InteropServices", "ComEventInterfaceAttribute");
+ }
+ }
+ }
+}
return null;
}
+ public override MethodDesc GetMethodWithEquivalentSignature(string name, MethodSignature signature, Instantiation substitution)
+ {
+ var metadataReader = this.MetadataReader;
+ var stringComparer = metadataReader.StringComparer;
+
+ foreach (var handle in _typeDefinition.GetMethods())
+ {
+ if (stringComparer.Equals(metadataReader.GetMethodDefinition(handle).Name, name))
+ {
+ var method = _module.GetMethod(handle, this);
+ if (signature == null || signature.EquivalentTo(method.Signature.ApplySubstitution(substitution)))
+ return method;
+ }
+ }
+
+ return null;
+ }
+
public override MethodDesc GetStaticConstructor()
{
var metadataReader = this.MetadataReader;
using System;
using System.Diagnostics;
using System.Reflection;
-using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
-namespace ILCompiler
+namespace Internal.TypeSystem
{
public enum EffectiveVisibility
{
TypeAttributes.NestedFamily => EffectiveVisibility.Family,
TypeAttributes.NestedFamANDAssem => EffectiveVisibility.FamilyAndAssembly,
TypeAttributes.NestedFamORAssem => EffectiveVisibility.FamilyOrAssembly,
+#if NETSTANDARD2_0
+ _ => throw new Exception(),
+#else
_ => throw new UnreachableException()
+#endif
};
}
private static EffectiveVisibility ToEffectiveVisibility(this MethodAttributes typeAttributes)
MethodAttributes.Family => EffectiveVisibility.Family,
MethodAttributes.FamANDAssem => EffectiveVisibility.FamilyAndAssembly,
MethodAttributes.FamORAssem => EffectiveVisibility.FamilyOrAssembly,
+#if NETSTANDARD2_0
+ _ => throw new Exception(),
+#else
_ => throw new UnreachableException()
+#endif
+ };
+ }
+
+ private static EffectiveVisibility ToEffectiveVisibility(this FieldAttributes typeAttributes)
+ {
+ return (typeAttributes & FieldAttributes.FieldAccessMask) switch
+ {
+ // PrivateScope == Compiler-Controlled in the ECMA spec. A member with this accessibility
+ // is only accessible through a MemberDef, not a MemberRef.
+ // As a result, it's only accessible within the current assembly, which is effectively the same rules as
+ // Family for our case.
+ FieldAttributes.PrivateScope => EffectiveVisibility.Assembly,
+ FieldAttributes.Public => EffectiveVisibility.Public,
+ FieldAttributes.Private => EffectiveVisibility.Private,
+ FieldAttributes.Assembly => EffectiveVisibility.Assembly,
+ FieldAttributes.Family => EffectiveVisibility.Family,
+ FieldAttributes.FamANDAssem => EffectiveVisibility.FamilyAndAssembly,
+ FieldAttributes.FamORAssem => EffectiveVisibility.FamilyOrAssembly,
+#if NETSTANDARD2_0
+ _ => throw new Exception(),
+#else
+ _ => throw new UnreachableException()
+#endif
};
}
(EffectiveVisibility.Assembly, EffectiveVisibility.FamilyAndAssembly) => EffectiveVisibility.FamilyAndAssembly,
(EffectiveVisibility.FamilyAndAssembly, EffectiveVisibility.Family) => EffectiveVisibility.FamilyAndAssembly,
(EffectiveVisibility.FamilyAndAssembly, EffectiveVisibility.Assembly) => EffectiveVisibility.FamilyAndAssembly,
+#if NETSTANDARD2_0
+ _ => throw new Exception(),
+#else
_ => throw new UnreachableException(),
+#endif
};
}
public static EffectiveVisibility GetEffectiveVisibility(this EcmaMethod method)
{
EffectiveVisibility visibility = method.Attributes.ToEffectiveVisibility();
-
+
for (EcmaType type = (EcmaType)method.OwningType; type is not null; type = (EcmaType)type.ContainingType)
{
visibility = visibility.ConstrainToVisibility(type.Attributes.ToEffectiveVisibility());
}
return visibility;
}
+
+ public static EffectiveVisibility GetEffectiveVisibility(this EcmaType type)
+ {
+ EffectiveVisibility visibility = type.Attributes.ToEffectiveVisibility();
+ type = (EcmaType)type.ContainingType;
+ for (; type is not null; type = (EcmaType)type.ContainingType)
+ {
+ visibility = visibility.ConstrainToVisibility(type.Attributes.ToEffectiveVisibility());
+ }
+ return visibility;
+ }
+
+ public static EffectiveVisibility GetEffectiveVisibility(this TypeDesc type)
+ {
+ var definitionType = type.GetTypeDefinition();
+ if (definitionType is MetadataType)
+ {
+ if (definitionType is EcmaType ecmaType)
+ {
+ return ecmaType.GetEffectiveVisibility();
+ }
+ return EffectiveVisibility.Public;
+ }
+ else
+ {
+ return EffectiveVisibility.Public;
+ }
+ }
+
+ public static EffectiveVisibility GetEffectiveVisibility(this EcmaField field)
+ {
+ // Treat all non-Ecma fields as always having public visibility
+ EffectiveVisibility visibility = field.Attributes.ToEffectiveVisibility();
+
+ for (EcmaType type = (EcmaType)field.OwningType; type is not null; type = (EcmaType)type.ContainingType)
+ {
+ visibility = visibility.ConstrainToVisibility(type.Attributes.ToEffectiveVisibility());
+ }
+ return visibility;
+ }
+
+ // Get the visibility declared on the field itself
+ // Treat all non-Ecma fields as always having public visibility
+ public static EffectiveVisibility GetAttributeEffectiveVisibility(this FieldDesc field)
+ {
+ if (field is EcmaField ecmaField)
+ {
+ return ecmaField.Attributes.ToEffectiveVisibility();
+ }
+ else
+ {
+ return EffectiveVisibility.Public;
+ }
+ }
+
+ public static EffectiveVisibility GetEffectiveVisibility(this FieldDesc field)
+ {
+ if (field is EcmaField ecmaField)
+ {
+ return GetEffectiveVisibility(ecmaField);
+ }
+ else
+ {
+ return EffectiveVisibility.Public;
+ }
+ }
}
}
// 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.Diagnostics;
namespace Internal.TypeSystem
Variant = 0x51,
}
- public class MarshalAsDescriptor
+ public class MarshalAsDescriptor: IEquatable<MarshalAsDescriptor>
{
private TypeDesc _marshallerType;
private string _cookie;
_marshallerType = customMarshallerType;
_cookie = cookie;
}
+
+ public bool Equals(MarshalAsDescriptor other)
+ {
+ if ((Type != other.Type) ||
+ (ArraySubType != other.ArraySubType) ||
+ (SizeParamIndex != other.SizeParamIndex) ||
+ (SizeConst != other.SizeConst))
+ return false;
+
+ return true;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is MarshalAsDescriptor other)
+ {
+ return Equals(other);
+ }
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return Type.GetHashCode() ^ (ArraySubType.GetHashCode() << 3);
+ }
}
}
return Context.GetMethodForRuntimeDeterminedType(method.GetTypicalMethodDefinition(), this);
}
+ public override MethodDesc GetMethodWithEquivalentSignature(string name, MethodSignature signature, Instantiation substitution)
+ {
+ MethodDesc method = _rawCanonType.GetMethodWithEquivalentSignature(name, signature, substitution);
+ if (method == null)
+ return null;
+ return Context.GetMethodForRuntimeDeterminedType(method.GetTypicalMethodDefinition(), this);
+ }
+
protected override TypeFlags ComputeTypeFlags(TypeFlags mask)
{
TypeFlags flags = 0;
<SignAssembly>true</SignAssembly>
<StrongNameKeyId>Open</StrongNameKeyId>
<RunAnalyzers>false</RunAnalyzers>
+ <DefineConstants>NETSTANDARD2_0</DefineConstants>
</PropertyGroup>
<Import Project="ILVerification.projitems" />
<Compile Include="$(ToolsCommonPath)TypeSystem\Common\InstantiatedType.MethodImpls.cs">
<Link>TypeSystem\Common\InstantiatedType.MethodImpls.cs</Link>
</Compile>
+ <Compile Include="$(ToolsCommonPath)TypeSystem\Common\InstantiatedType.TypeEquivalence.cs">
+ <Link>TypeSystem\Common\InstantiatedType.TypeEquivalence.cs</Link>
+ </Compile>
<Compile Include="$(ToolsCommonPath)TypeSystem\Common\LayoutInt.cs">
<Link>TypeSystem\Common\LayoutInt.cs</Link>
</Compile>
<Compile Include="$(ToolsCommonPath)TypeSystem\Common\TypeDesc.ToString.cs">
<Link>TypeSystem\Common\TypeDesc.ToString.cs</Link>
</Compile>
+ <Compile Include="$(ToolsCommonPath)TypeSystem\Common\TypeDesc.TypeEquivalence.cs">
+ <Link>TypeSystem\Common\TypeDesc.TypeEquivalence.cs</Link>
+ </Compile>
<Compile Include="$(ToolsCommonPath)TypeSystem\Common\DefType.cs">
<Link>TypeSystem\Common\DefType.cs</Link>
</Compile>
<Compile Include="$(ToolsCommonPath)TypeSystem\Ecma\EcmaType.Interfaces.cs">
<Link>Ecma\EcmaType.Interfaces.cs</Link>
</Compile>
+ <Compile Include="$(ToolsCommonPath)TypeSystem\Ecma\EcmaType.TypeEquivalence.cs">
+ <Link>Ecma\EcmaType.TypeEquivalence.cs</Link>
+ </Compile>
+ <Compile Include="$(ToolsCommonPath)TypeSystem\Ecma\EffectiveVisibility.cs">
+ <Link>Ecma\EffectiveVisibility.cs</Link>
+ </Compile>
<Compile Include="$(ToolsCommonPath)TypeSystem\Ecma\MetadataExtensions.cs">
<Link>Ecma\MetadataExtensions.cs</Link>
</Compile>
var methodDecl = type.EcmaModule.GetMethod(methodImpl.MethodDeclaration);
// Validate that all MethodImpls actually match signatures closely enough
- if (!methodBody.Signature.ApplySubstitution(type.Instantiation).EqualsWithCovariantReturnType(methodDecl.Signature.ApplySubstitution(type.Instantiation)))
+ if (!methodBody.Signature.ApplySubstitution(type.Instantiation).EquivalentWithCovariantReturnType(methodDecl.Signature.ApplySubstitution(type.Instantiation)))
{
AddTypeValidationError(type, $"MethodImpl with Body '{methodBody}' and Decl '{methodDecl}' do not have matching signatures");
return false;
if ((virtualMethod.OwningType != type.BaseType) && (virtualMethod.OwningType != type) && (baseTypeVirtualMethodAlgorithm != null))
{
var implementationOnBaseType = baseTypeVirtualMethodAlgorithm.FindVirtualFunctionTargetMethodOnObjectType(virtualMethod, type.BaseType);
- if (!implementationMethod.Signature.ApplySubstitution(type.Instantiation).EqualsWithCovariantReturnType(implementationOnBaseType.Signature.ApplySubstitution(type.Instantiation)))
+ if (!implementationMethod.Signature.ApplySubstitution(type.Instantiation).EquivalentWithCovariantReturnType(implementationOnBaseType.Signature.ApplySubstitution(type.Instantiation)))
{
AddTypeValidationError(type, $"Virtual method '{virtualMethod}' overriden by method '{implementationMethod}' does not satisfy the covariant return type introduced with '{implementationOnBaseType}'");
return false;
}
}
+ if (type.TypeIdentifierData != null)
+ {
+ if (!type.TypeHasCharacteristicsRequiredToBeLoadableTypeEquivalentType)
+ {
+ return false;
+ }
+ }
+
return true;
}
catch (Exception ex)
public MethodDesc ResolveVirtualMethod(MethodDesc declMethod, TypeDesc implType, out CORINFO_DEVIRTUALIZATION_DETAIL devirtualizationDetail)
{
+ if (declMethod.OwningType.IsInterface)
+ {
+ // The virtual method resolution algorithm in the managed type system is not implemented to work correctly
+ // in the presence of calling type equivalent interfaces.
+ // Notably:
+ // If the decl is to a interface equivalent to, but not equal to any interface implemented on the
+ // owning type, then the logic for matching up methods by method index is not present.
+ // AND
+ // If the owningType implements multiple different type equivalent interfaces that are all mutually
+ // equivalent, the implementation for finding the correct implementation method requires walking the
+ // type hierarchy and searching for exact and equivalent matches at each level (much like variance)
+ // This logic is also currently unimplemented.
+ // NOTE: We do not currently have tests in the runtime suite which cover these cases
+ if (declMethod.OwningType.HasTypeEquivalence)
+ {
+ // To protect against this, require that the implType implement exactly the right interface, and
+ // no additional interfaces that are equivalent
+ bool foundExactMatch = false;
+ bool foundEquivalentMatch = false;
+ foreach (var @interface in implType.RuntimeInterfaces)
+ {
+ if (@interface == declMethod.OwningType)
+ {
+ foundExactMatch = true;
+ continue;
+ }
+ if (@interface.IsEquivalentTo(declMethod.OwningType))
+ {
+ foundEquivalentMatch = true;
+ }
+ }
+
+ if (!foundExactMatch || foundEquivalentMatch)
+ {
+ devirtualizationDetail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_FAILED_TYPE_EQUIVALENCE;
+ return null;
+ }
+ }
+ }
+
return _devirtualizationManager.ResolveVirtualMethod(declMethod, implType, out devirtualizationDetail);
}
return _asyncStateMachineBox;
}
}
+
+ public override bool SupportsTypeEquivalence => Target.IsWindows;
+ public override bool SupportsCOMInterop => Target.IsWindows;
}
internal class VectorOfTFieldLayoutAlgorithm : FieldLayoutAlgorithm
<Compile Include="Compiler\DependencyAnalysis\ReadyToRunSymbolNodeFactory.cs" />
<Compile Include="Compiler\DependencyAnalysis\SortableDependencyNodeCompilerSpecific.cs" />
<Compile Include="Compiler\DependencyAnalysis\TypeAndMethod.cs" />
- <Compile Include="Compiler\EffectiveVisibility.cs" />
<Compile Include="Compiler\IRootingServiceProvider.cs" />
<Compile Include="Compiler\ReadyToRunCompilationModuleGroupBase.cs" />
<Compile Include="Compiler\PettisHansenSort\CallGraphNode.cs" />
}
}
+ // We validate the safety of the signature here, as it could have been adjusted
+ // by virtual resolution during getCallInfo (virtual resolution could find a result using type equivalence)
+ ValidateSafetyOfUsingTypeEquivalenceInSignature(targetMethod.GetTypicalMethodDefinition().Signature);
+
// OK, if the EE said we're not doing a stub dispatch then just return the kind to
// the caller. No other kinds of virtual calls have extra information attached.
switch (pResult->kind)
// Implemented for JIT and NativeAOT only for now.
return false;
}
+
+ private void ValidateSafetyOfUsingTypeEquivalenceInSignature(MethodSignature signature)
+ {
+ // Type equivalent valuetypes not in the current version bubble are problematic, and cannot be referred to in our current token
+ // scheme except through type references. So we need to detect them, and if they aren't referred to by type reference from a module
+ // in the current build, then we need to fallback to runtime jit.
+ ValidateSafetyOfUsingTypeEquivalenceOfType(signature.ReturnType);
+ foreach (var type in signature)
+ {
+ ValidateSafetyOfUsingTypeEquivalenceOfType(type);
+ }
+ }
+
+ void ValidateSafetyOfUsingTypeEquivalenceOfType(TypeDesc type)
+ {
+ if (type.IsValueType && type.IsTypeDefEquivalent && !_compilation.CompilationModuleGroup.VersionsWithTypeReference(type))
+ {
+ // Technically this is a bit pickier than needed, as cross module inlineable cases will be hit by this, but type equivalence is a
+ // rarely used feature, and we can fix that if we need to.
+ throw new RequiresRuntimeJitException($"Type equivalent valuetype '{type}' not directly referenced from member reference");
+ }
+ }
}
}
class GenericStructTypeWithThreeParams<T, U, V>
{
}
+
+ interface InterfaceGenericType<T>
+ {
+ }
}
}
public int Value { get { return _val; } }
}
+
+ public sealed class TypeIdentifierAttribute : Attribute
+ {
+ public TypeIdentifierAttribute() { }
+ public TypeIdentifierAttribute(string scope, string identifier)
+ {
+ Scope = scope;
+ Identifier = identifier;
+ }
+
+ public string Scope { get; }
+ public string Identifier { get; }
+ }
+
+ public enum UnmanagedType
+ {
+ Bool = 2,
+ I1 = 3,
+ U1 = 4,
+ I2 = 5,
+ U2 = 6,
+ I4 = 7,
+ U4 = 8,
+ I8 = 9,
+ U8 = 10,
+ R4 = 11,
+ R8 = 12,
+ Currency = 15,
+ BStr = 19,
+ LPStr = 20,
+ LPWStr = 21,
+ LPTStr = 22,
+ ByValTStr = 23,
+ IUnknown = 25,
+ IDispatch = 26,
+ Struct = 27,
+ Interface = 28,
+ SafeArray = 29,
+ ByValArray = 30,
+ SysInt = 31,
+ SysUInt = 32,
+ VBByRefStr = 34,
+ AnsiBStr = 35,
+ TBStr = 36,
+ VariantBool = 37,
+ FunctionPtr = 38,
+ AsAny = 40,
+ LPArray = 42,
+ LPStruct = 43,
+ CustomMarshaler = 44,
+ Error = 45,
+ IInspectable = 46,
+ HString = 47,
+ LPUTF8Str = 48
+ }
+ public sealed class MarshalAsAttribute : Attribute
+ {
+ public MarshalAsAttribute(UnmanagedType unmanagedType) { }
+ }
+
+ public sealed class ComImportAttribute : Attribute
+ {
+ }
+
+ public sealed class ComEventInterfaceAttribute : Attribute
+ {
+ public ComEventInterfaceAttribute(Type SourceInterface, Type EventProvider) { }
+ }
+
+ public sealed class GuidAttribute : Attribute
+ {
+ public GuidAttribute(string guid) { }
+ }
}
namespace System.Runtime.CompilerServices
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\ILCompiler.TypeSystem\ILCompiler.TypeSystem.csproj" />
+ <ProjectReference Include="..\ILCompiler.TypeSystem\ILCompiler.TypeSystem.csproj">
+ <Private>True</Private>
+ </ProjectReference>
<!-- Make sure the test data gets built -->
<ProjectReference Include="CoreTestAssembly\CoreTestAssembly.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ <Private>True</Private>
</ProjectReference>
<ProjectReference Include="ILTestAssembly\ILTestAssembly.ilproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ <Private>True</Private>
+ </ProjectReference>
+ <ProjectReference Include="TypeEquivalenceAssembly\TypeEquivalenceAssembly1.csproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ <Private>True</Private>
+ </ProjectReference>
+ <ProjectReference Include="TypeEquivalenceAssembly\TypeEquivalenceAssembly2.csproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ <Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="SyntheticVirtualOverrideTests.cs" />
<Compile Include="SyntheticVirtualOverrideTests.DiagnosticName.cs" />
<Compile Include="TestMetadataFieldLayoutAlgorithm.cs" />
+ <Compile Include="TypeEquivalenceTests.cs" />
<Compile Include="TypeNameParsingTests.cs" />
<Compile Include="UniversalGenericFieldLayoutTests.cs" />
<Compile Include="ValueTypeShapeCharacteristicsTests.cs" />
public override bool SupportsUniversalCanon => true;
public override bool SupportsCanon => true;
+
+ public override bool SupportsCOMInterop => true;
+ public override bool SupportsTypeEquivalence => true;
}
}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <SkipTestRun>true</SkipTestRun>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <!-- Don't add references to the netstandard platform since this is a core assembly -->
+ <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
+ <!-- CSC needs explicit metadata version when it has no core library to reference -->
+ <RuntimeMetadataVersion>v4.0.30319</RuntimeMetadataVersion>
+ <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
+ <RunAnalyzers>false</RunAnalyzers>
+ <DefineConstants>TYPEEQUIVALENCEASSEMBLY_1</DefineConstants>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\CoreTestAssembly\CoreTestAssembly.csproj">
+ <Name>CoreTestAssembly</Name>
+ </ProjectReference>
+ </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <SkipTestRun>true</SkipTestRun>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <!-- Don't add references to the netstandard platform since this is a core assembly -->
+ <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
+ <!-- CSC needs explicit metadata version when it has no core library to reference -->
+ <RuntimeMetadataVersion>v4.0.30319</RuntimeMetadataVersion>
+ <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
+ <RunAnalyzers>false</RunAnalyzers>
+ <DefineConstants>TYPEEQUIVALENCEASSEMBLY_2</DefineConstants>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\CoreTestAssembly\CoreTestAssembly.csproj">
+ <Name>CoreTestAssembly</Name>
+ </ProjectReference>
+ </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+#pragma warning disable 169
+
+namespace TypesWhichDoNotLoad
+{
+ // A case where a field is not public
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type1")]
+ public struct Type1
+ {
+ int field;
+ }
+
+ // A case where the type is not both public
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type2")]
+ enum Type2
+ {
+ }
+
+ // A case where the type is not both public
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type3")]
+ struct Type3
+ {
+ }
+
+ // A case where the type is not both public
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type4")]
+ delegate object Type4(object param);
+
+ // A case where the type is not nested public
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type4_IGNORE")]
+ public struct Type4_IGNORE
+ {
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type5")]
+ struct Type5
+ { }
+ }
+
+ // A case with a static field
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type6")]
+ public struct Type6
+ {
+ public static int field;
+ }
+
+ // A case with an instance method
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type7")]
+ public struct Type7
+ {
+ public void Method() { }
+ }
+
+ // A case which is a normal interface (not ComImport of ComEventInterface)
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type8")]
+ public interface Type8 { }
+
+ // A generic type
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type9")]
+ public struct Type9<T> { }
+
+ // A type nested in a non TypeEquivalent type
+ public struct NonTypeEquivalent
+ {
+ [TypeIdentifier("TypesWhichDoNotLoad", "Type10")]
+ public struct Type10 { }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+#pragma warning disable 169
+
+namespace TypesWhichDoNotMatch
+{
+ // A case where 1 type has a field, and another does not
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type1")]
+ public struct Type1
+ {
+#if TYPEEQUIVALENCEASSEMBLY_1
+ public int field;
+#endif
+ }
+
+ // A case where there is a static method on the type
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type2")]
+ public struct Type2
+ {
+ public static void Method() { }
+ }
+
+ // A case where a delegate varies in signature
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type3")]
+ public delegate
+#if TYPEEQUIVALENCEASSEMBLY_1
+ object
+#else
+ string
+#endif
+ Type3();
+
+ // A case where the type names are not the same
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type4")]
+ public struct
+#if TYPEEQUIVALENCEASSEMBLY_1
+ Type4
+#else
+ Type4NotQuite
+#endif
+ { }
+
+ // A case where MarshalAs behavior is different
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type5")]
+ public struct Type5
+ {
+#if TYPEEQUIVALENCEASSEMBLY_1
+ [MarshalAs(UnmanagedType.Bool)]
+#else
+ [MarshalAs(UnmanagedType.VariantBool)]
+#endif
+ public bool X;
+ }
+
+ // A different case where MarshalAs behavior is different
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type6")]
+ public struct Type6
+ {
+#if TYPEEQUIVALENCEASSEMBLY_1
+ [MarshalAs(UnmanagedType.Bool)]
+#endif
+ public bool X;
+ }
+
+ // A case where fixed layouts are not the same
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type7")]
+ [StructLayout(LayoutKind.Explicit)]
+ public struct Type7
+ {
+ [FieldOffset(0)]
+ public int Lol;
+#if TYPEEQUIVALENCEASSEMBLY_1
+ [FieldOffset(20)]
+#else
+ [FieldOffset(21)]
+#endif
+ public byte Omg;
+ }
+
+ // A case where the MDArray is different
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type8")]
+ public struct Type8
+ {
+ public
+#if TYPEEQUIVALENCEASSEMBLY_1
+ TypesWhichMatch.Type4[,,]
+#else
+ TypesWhichMatch.Type4[,,,]
+#endif
+ MDArray;
+ }
+
+ // A case where the underlying data of the enum does not match
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type9")]
+ public enum Type9 :
+#if TYPEEQUIVALENCEASSEMBLY_1
+ byte
+#else
+ sbyte
+#endif
+ {
+ }
+
+ // A case with a function pointer
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type10")]
+ public struct Type10
+ {
+ public unsafe delegate*<TypesWhichMatch.Type4, void> functionPointer;
+ }
+
+ // A case where the overall size is different
+#if TYPEEQUIVALENCEASSEMBLY_1
+ [StructLayout(LayoutKind.Explicit, Size = 40)]
+#else
+ [StructLayout(LayoutKind.Explicit, Size = 41)]
+#endif
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type11")]
+ public struct Type11
+ {
+ [FieldOffset(0)]
+ public int Lol;
+ [FieldOffset(20)]
+ public byte Omg;
+
+ // A test case where the type itself would match, but its containing type does not
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type12")]
+ public struct Type12 { }
+ }
+
+ // No layoutkind auto struct will ever match (but it will load)
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type13")]
+ [StructLayout(LayoutKind.Auto)]
+ public struct Type13 { }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+#pragma warning disable 169
+
+#if TYPEEQUIVALENCEASSEMBLY_1
+public class TypeEquivalenceAssembly1
+{}
+#else
+public class TypeEquivalenceAssembly2
+{ }
+#endif
+
+namespace TypesWhichMatch
+{
+ [TypeIdentifier("TypesWhichMatch", "Type1")]
+ public enum Type1
+ {
+ }
+
+ [TypeIdentifier("TypesWhichMatch", "Type2")]
+ public enum Type2
+ {
+// The actual values of the literal enums are not considered relevant for type equivalence
+#if TYPEEQUIVALENCEASSEMBLY_1
+ First = 1,
+ Second = 2,
+#else
+ First = 2,
+ Second = 1,
+#endif
+ }
+
+ [TypeIdentifier("TypesWhichMatch", "Type3")]
+ public struct Type3
+ {
+ }
+
+ [TypeIdentifier("TypesWhichMatch", "Type4")]
+ public struct Type4
+ {
+ public int X;
+ }
+
+ [TypeIdentifier("TypesWhichMatch", "Type5")]
+ public struct Type5
+ {
+ public int X;
+ public Type4 type4;
+ }
+
+
+ [TypeIdentifier("TypesWhichMatch", "Type6")]
+ public delegate void Type6(int X);
+
+ [TypeIdentifier("TypesWhichMatch", "Type7")]
+ public delegate void Type7(int X);
+
+ [TypeIdentifier("TypesWhichMatch", "Type9")]
+ [ComImport]
+ [GuidAttribute("9ED54F84-A89D-4fcd-A854-44251E925F09")]
+ public interface Type9
+ {
+ // Mismatched methods don't impede equivalence for the purpose of IsEquivalent, but they will interfere with actual dispatch
+ void Method();
+#if TYPEEQUIVALENCEASSEMBLY_1
+ void Method2(int x);
+#else
+ void Method2(short x);
+ void Method3(int x, Type4 type4);
+#endif
+
+ // Test nested type
+ [TypeIdentifier("TypesWhichMatch", "Type10")]
+ public struct Type10
+ {
+ [MarshalAs(UnmanagedType.Bool)]
+ public bool X;
+ }
+ }
+
+ [TypeIdentifier("TypesWhichMatch", "Type11")]
+ [StructLayout(LayoutKind.Explicit, Size = 40)]
+ public struct Type11
+ {
+ [FieldOffset(0)]
+ public int Lol;
+ [FieldOffset(20)]
+ public byte Omg;
+ }
+
+ [TypeIdentifier("TypesWhichMatch", "Type12")]
+ [StructLayout(LayoutKind.Explicit)]
+ public struct Type12
+ {
+ [FieldOffset(0)]
+ public int Lol;
+ [FieldOffset(20)]
+ public byte Omg;
+ }
+
+ [TypeIdentifier("TypesWhichMatch", "Type13")]
+ [ComEventInterface(null, null)]
+ public interface Type13
+ {
+ }
+
+ [TypeIdentifier("TypesWhichMatch", "Type14")]
+ public struct Type14
+ {
+ // Validate that arrays, pointers and mdarrays are handled appropriately
+ public Type4[] SzArray;
+ public unsafe Type4* Ptr;
+ public Type4[,,] MDArray;
+ }
+
+ // A case with a function pointer
+ [TypeIdentifier("TypesWhichDoNotMatch", "Type15")]
+ public struct Type15
+ {
+ public unsafe delegate*<int, void> functionPointer;
+ }
+
+}
--- /dev/null
+// 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.Metadata;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+using Xunit;
+using Xunit.Abstractions;
+
+namespace TypeSystemTests
+{
+ public class Entrypoint
+ {
+ class Logger : ITestOutputHelper
+ {
+ void ITestOutputHelper.WriteLine(string message) => Console.WriteLine(message);
+ void ITestOutputHelper.WriteLine(string format, params object[] args) => Console.WriteLine(format, args);
+ }
+
+ public static void NotQuiteMain()
+ {
+ TypeEquivalenceTests tests = new TypeEquivalenceTests(new Logger());
+ tests.TestTypesWhichShouldMatch();
+ }
+ }
+ public class TypeEquivalenceTests
+ {
+ private TestTypeSystemContext _context;
+ private EcmaModule _testModule1;
+ private EcmaModule _testModule2;
+
+ private MetadataType _referenceType;
+ private MetadataType _otherReferenceType;
+ private MetadataType _structType;
+ private MetadataType _otherStructType;
+ private MetadataType _genericReferenceType;
+ private MetadataType _genericStructType;
+ private MetadataType _genericReferenceTypeWithThreeParams;
+ private MetadataType _genericStructTypeWithThreeParams;
+ private MetadataType _interfaceGenericType;
+
+ private ITestOutputHelper _logger;
+
+ public TypeEquivalenceTests(ITestOutputHelper outputHelper)
+ {
+ _logger = outputHelper;
+ _context = new TestTypeSystemContext(TargetArchitecture.Unknown);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule1 = (EcmaModule)_context.CreateModuleForSimpleName("TypeEquivalenceAssembly1");
+ _testModule2 = (EcmaModule)_context.CreateModuleForSimpleName("TypeEquivalenceAssembly2");
+
+ _referenceType = systemModule.GetType("Canonicalization", "ReferenceType");
+ _otherReferenceType = systemModule.GetType("Canonicalization", "OtherReferenceType");
+ _structType = systemModule.GetType("Canonicalization", "StructType");
+ _otherStructType = systemModule.GetType("Canonicalization", "OtherStructType");
+ _genericReferenceType = systemModule.GetType("Canonicalization", "GenericReferenceType`1");
+ _genericStructType = systemModule.GetType("Canonicalization", "GenericStructType`1");
+ _genericReferenceTypeWithThreeParams = systemModule.GetType("Canonicalization", "GenericReferenceTypeWithThreeParams`3");
+ _genericStructTypeWithThreeParams = systemModule.GetType("Canonicalization", "GenericStructTypeWithThreeParams`3");
+ _interfaceGenericType = systemModule.GetType("Canonicalization", "InterfaceGenericType`1");
+ }
+
+ private IEnumerable<TypeDefinitionHandle> GetAllNestedTypes(MetadataReader metadataReader, TypeDefinition typeDef)
+ {
+ foreach (var nestedHandle in typeDef.GetNestedTypes())
+ {
+ yield return nestedHandle;
+ var nestedType = metadataReader.GetTypeDefinition(nestedHandle);
+ foreach (var moreNestedHandle in GetAllNestedTypes(metadataReader, nestedType))
+ {
+ yield return moreNestedHandle;
+ }
+ }
+ }
+
+ private IEnumerable<TypeDefinitionHandle> GetAllTypesInNamespace(EcmaModule module, string @namespace)
+ {
+ var metadataReader = module.MetadataReader;
+ foreach (var typeDefHandle in metadataReader.TypeDefinitions)
+ {
+ var typeDef = metadataReader.GetTypeDefinition(typeDefHandle);
+ if (typeDef.IsNested)
+ {
+ continue; // Ignore nested types for now
+ }
+
+ if (metadataReader.StringComparer.Equals(typeDef.Namespace, @namespace))
+ {
+ yield return typeDefHandle;
+ foreach (var nestedHandle in GetAllNestedTypes(metadataReader, typeDef))
+ {
+ yield return nestedHandle;
+ }
+ }
+ }
+ }
+
+ private static bool IsEqualCustomAttributeName(CustomAttributeHandle attributeHandle, MetadataReader metadataReader,
+ string attributeNamespace, string attributeName)
+ {
+ StringHandle namespaceHandle, nameHandle;
+ if (!metadataReader.GetAttributeNamespaceAndName(attributeHandle, out namespaceHandle, out nameHandle))
+ return false;
+
+ return metadataReader.StringComparer.Equals(namespaceHandle, attributeNamespace)
+ && metadataReader.StringComparer.Equals(nameHandle, attributeName);
+ }
+
+ private string GetTypeIdentiferFromTypeDef(EcmaModule module, TypeDefinitionHandle typeDefHandle)
+ {
+ CustomAttributeTypeProvider customAttributeTypeProvider = new CustomAttributeTypeProvider(module);
+ var typeDef = module.MetadataReader.GetTypeDefinition(typeDefHandle);
+ foreach (var attributeHandle in typeDef.GetCustomAttributes())
+ {
+ if (IsEqualCustomAttributeName(attributeHandle, module.MetadataReader, "System.Runtime.InteropServices", "TypeIdentifierAttribute"))
+ {
+ var typeIdentifierAttribute = module.MetadataReader.GetCustomAttribute(attributeHandle).DecodeValue(customAttributeTypeProvider);
+
+ if (typeIdentifierAttribute.FixedArguments.Length != 2)
+ throw new Exception("Unexpected in this test suite");
+
+ return $"{typeIdentifierAttribute.FixedArguments[0].Value}_{typeIdentifierAttribute.FixedArguments[1].Value}";
+ }
+ }
+
+ return null;
+ }
+
+ private Dictionary<string, TypeDefinitionHandle> GetTypeIdentifierAssociatedTypesInNamespace(EcmaModule module, string @namespace)
+ {
+ Dictionary<string, TypeDefinitionHandle> result = new Dictionary<string, TypeDefinitionHandle>();
+ foreach (var typeDef in GetAllTypesInNamespace(module, @namespace))
+ {
+ string typeId = GetTypeIdentiferFromTypeDef(module, typeDef);
+ if (typeId != null)
+ {
+ result.Add(typeId, typeDef);
+ }
+ }
+ return result;
+ }
+
+ private IEnumerable<ValueTuple<TypeDesc, TypeDesc>> GetTypesWhichClaimMatchingTypeIdentifiersInNamespace(string @namespace)
+ {
+ var module1Types = GetTypeIdentifierAssociatedTypesInNamespace(_testModule1, @namespace);
+ var module2Types = GetTypeIdentifierAssociatedTypesInNamespace(_testModule2, @namespace);
+
+ foreach (var data in module1Types)
+ {
+ if (module2Types.TryGetValue(data.Key, out var typeDef2))
+ {
+ yield return ((TypeDesc)_testModule1.GetObject(data.Value), (TypeDesc)_testModule2.GetObject(typeDef2));
+ }
+ }
+ }
+
+ [Fact]
+ public void TestTypesWhichShouldMatch()
+ {
+ foreach (var typePair in GetTypesWhichClaimMatchingTypeIdentifiersInNamespace("TypesWhichMatch"))
+ {
+ _logger.WriteLine($"Comparing {typePair.Item1} to {typePair.Item2}");
+ Assert.NotEqual(typePair.Item1, typePair.Item2);
+ Assert.True(typePair.Item1.IsEquivalentTo(typePair.Item2));
+ Assert.True(typePair.Item1.TypeHasCharacteristicsRequiredToBeLoadableTypeEquivalentType);
+ Assert.True(typePair.Item2.TypeHasCharacteristicsRequiredToBeLoadableTypeEquivalentType);
+ }
+ }
+
+ [Fact]
+ public void TestGenericInterfacesWithTypeEquivalence()
+ {
+ foreach (var typePair in GetTypesWhichClaimMatchingTypeIdentifiersInNamespace("TypesWhichMatch"))
+ {
+ var gen1 = _interfaceGenericType.MakeInstantiatedType(typePair.Item1);
+ var gen2 = _interfaceGenericType.MakeInstantiatedType(typePair.Item2);
+
+ _logger.WriteLine($"Comparing {gen1} to {gen2}");
+ Assert.NotEqual(gen1, gen2);
+ Assert.True(gen1.IsEquivalentTo(gen2));
+ }
+ }
+
+ [Fact]
+ public void TestGenericClassesWithTypeEquivalence()
+ {
+ foreach (var typePair in GetTypesWhichClaimMatchingTypeIdentifiersInNamespace("TypesWhichMatch"))
+ {
+ var gen1 = _genericReferenceType.MakeInstantiatedType(typePair.Item1);
+ var gen2 = _genericReferenceType.MakeInstantiatedType(typePair.Item2);
+
+ _logger.WriteLine($"Comparing{gen1} to {gen2}");
+ Assert.NotEqual(gen1, gen2);
+ Assert.False(gen1.IsEquivalentTo(gen2));
+ }
+ }
+
+ [Fact]
+ public void TestGenericStructsWithTypeEquivalence()
+ {
+ foreach (var typePair in GetTypesWhichClaimMatchingTypeIdentifiersInNamespace("TypesWhichMatch"))
+ {
+ var gen1 = _genericStructType.MakeInstantiatedType(typePair.Item1);
+ var gen2 = _genericStructType.MakeInstantiatedType(typePair.Item2);
+
+ _logger.WriteLine($"Comparing {gen1} to {gen2}");
+ Assert.NotEqual(gen1, gen2);
+ Assert.False(gen1.IsEquivalentTo(gen2));
+ }
+ }
+
+ [Fact]
+ public void TestTypesWhichShouldNotMatch()
+ {
+ foreach (var typePair in GetTypesWhichClaimMatchingTypeIdentifiersInNamespace("TypesWhichDoNotMatch"))
+ {
+ _logger.WriteLine($"Comparing {typePair.Item1} to {typePair.Item2}");
+ Assert.False(typePair.Item1.IsEquivalentTo(typePair.Item2));
+ Assert.True(typePair.Item1.TypeHasCharacteristicsRequiredToBeLoadableTypeEquivalentType);
+ Assert.True(typePair.Item2.TypeHasCharacteristicsRequiredToBeLoadableTypeEquivalentType);
+ }
+ }
+
+ [Fact]
+ public void TestTypesWhichShouldNotBeLoadable()
+ {
+ foreach (var typePair in GetTypesWhichClaimMatchingTypeIdentifiersInNamespace("TypesWhichDoNotLoad"))
+ {
+ if (((MetadataType)typePair.Item1).Name.EndsWith("IGNORE"))
+ continue;
+
+ _logger.WriteLine($"Checking load behavior of {typePair.Item1}");
+ Assert.False(typePair.Item1.TypeHasCharacteristicsRequiredToBeLoadableTypeEquivalentType);
+ }
+ }
+ }
+}
<Compile Include="..\..\Common\TypeSystem\Common\CastingHelper.cs">
<Link>TypeSystem\Common\CastingHelper.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\TypeSystem\Common\CastingHelper.TypeEquivalence.cs">
+ <Link>TypeSystem\Common\CastingHelper.TypeEquivalence.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\TypeSystem\Common\ConstructedTypeRewritingHelpers.cs">
<Link>TypeSystem\Common\ConstructedTypeRewritingHelpers.cs</Link>
</Compile>
<Compile Include="..\..\Common\TypeSystem\Common\InstantiatedType.MethodImpls.cs">
<Link>TypeSystem\Common\InstantiatedType.MethodImpls.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\TypeSystem\Common\InstantiatedType.TypeEquivalence.cs">
+ <Link>TypeSystem\Common\InstantiatedType.TypeEquivalence.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\TypeSystem\Common\LayoutInt.cs">
<Link>TypeSystem\Common\LayoutInt.cs</Link>
</Compile>
<Compile Include="..\..\Common\TypeSystem\Common\TypeDesc.Interfaces.cs">
<Link>TypeSystem\Common\TypeDesc.Interfaces.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\TypeSystem\Common\TypeDesc.TypeEquivalence.cs">
+ <Link>TypeSystem\Common\TypeDesc.TypeEquivalence.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\TypeSystem\Common\DefType.cs">
<Link>TypeSystem\Common\DefType.cs</Link>
</Compile>
<Compile Include="..\..\Common\TypeSystem\Ecma\EcmaType.Sorting.cs">
<Link>Ecma\EcmaType.Sorting.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\TypeSystem\Ecma\EcmaType.TypeEquivalence.cs">
+ <Link>Ecma\EcmaType.TypeEquivalence.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\TypeSystem\Ecma\EffectiveVisibility.cs">
+ <Link>Ecma\EffectiveVisibility.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\TypeSystem\Ecma\PrimitiveTypeProvider.cs">
<Link>Ecma\PrimitiveTypeProvider.cs</Link>
</Compile>
// Check if type is generic
if (HasInstantiation())
{
- // Limit variance on generics only to interfaces
+ // Limit equivalence on generics only to interfaces
if (!IsInterface() || !pOtherMT->IsInterface())
{
fEquivalent = FALSE;
--- /dev/null
+// 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.Linq;
+using System.Text;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+using Xunit;
+
+// This test shares its logic with the managed type system test suite, and seeks to ensure the runtime agrees with it
+namespace istypeequivalent
+{
+ public class Test
+ {
+ private static IEnumerable<Type> GetAllTypesInNamespace(Module module, string @namespace)
+ {
+ foreach (var type in module.GetTypes())
+ {
+ if (type.Namespace == @namespace)
+ {
+ Console.WriteLine($"Found {type}");
+ yield return type;
+ }
+ }
+ }
+
+ private static string GetTypeIdentiferFromType(Type type)
+ {
+ foreach (var ca in type.GetCustomAttributes())
+ {
+ if (ca is TypeIdentifierAttribute typeId)
+ {
+ return $"{typeId.Scope}_{typeId.Identifier}";
+ }
+ }
+
+ return null;
+ }
+
+ private static Dictionary<string, Type> GetTypeIdentifierAssociatedTypesInNamespace(Module module, string @namespace)
+ {
+ Dictionary<string, Type> result = new Dictionary<string, Type>();
+ foreach (var typeDef in GetAllTypesInNamespace(module, @namespace))
+ {
+ string typeId = GetTypeIdentiferFromType(typeDef);
+ if (typeId != null)
+ {
+ result.Add(typeId, typeDef);
+ }
+ }
+ return result;
+ }
+
+ private static IEnumerable<ValueTuple<Type, Type>> GetTypesWhichClaimMatchingTypeIdentifiersInNamespace(string @namespace)
+ {
+ var module1Types = GetTypeIdentifierAssociatedTypesInNamespace(typeof(TypeEquivalenceAssembly1).Module, @namespace);
+ var module2Types = GetTypeIdentifierAssociatedTypesInNamespace(typeof(TypeEquivalenceAssembly2).Module, @namespace);
+
+ foreach (var data in module1Types)
+ {
+ if (module2Types.TryGetValue(data.Key, out var typeDef2))
+ {
+ yield return (data.Value, typeDef2);
+ }
+ }
+ }
+
+ public static void TestTypesWhichShouldMatch()
+ {
+ foreach (var typePair in GetTypesWhichClaimMatchingTypeIdentifiersInNamespace("TypesWhichMatch"))
+ {
+ Console.WriteLine($"Comparing {typePair.Item1} to {typePair.Item2}");
+ Assert.NotEqual(typePair.Item1, typePair.Item2);
+ Assert.True(typePair.Item1.IsEquivalentTo(typePair.Item2));
+ }
+ }
+
+ public static void TestTypesWhichShouldNotMatch()
+ {
+ foreach (var typePair in GetTypesWhichClaimMatchingTypeIdentifiersInNamespace("TypesWhichDoNotMatch"))
+ {
+ Console.WriteLine($"Comparing {typePair.Item1} to {typePair.Item2}");
+ Assert.False(typePair.Item1.IsEquivalentTo(typePair.Item2));
+ }
+ }
+
+ public static int Main()
+ {
+ if (!OperatingSystem.IsWindows())
+ {
+ return 100;
+ }
+
+ TestTypesWhichShouldMatch();
+ TestTypesWhichShouldNotMatch();
+
+ return 100;
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ <MonoAotIncompatible>true</MonoAotIncompatible>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="istypeequivalent.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="typeequivalenttypes_1.csproj" />
+ <ProjectReference Include="typeequivalenttypes_2.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetPathOfFileAbove(TypeEquivalence.targets))" />
+</Project>
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <CLRTestKind>SharedLibrary</CLRTestKind>
+ <DefineConstants>$(DefineConstants);TYPEEQUIVALENCEASSEMBLY_1</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="../../../../coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TypeEquivalenceAssembly/TypesWhichDoNotMatch.cs" />
+ <Compile Include="../../../../coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TypeEquivalenceAssembly/TypesWhichMatch.cs" />
+ </ItemGroup>
+</Project>
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <CLRTestKind>SharedLibrary</CLRTestKind>
+ <DefineConstants>$(DefineConstants);TYPEEQUIVALENCEASSEMBLY_2</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="../../../../coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TypeEquivalenceAssembly/TypesWhichDoNotMatch.cs" />
+ <Compile Include="../../../../coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TypeEquivalenceAssembly/TypesWhichMatch.cs" />
+ </ItemGroup>
+</Project>
--- /dev/null
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.20326.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.AMD64chk
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly basetestclassesil
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module basetestclassesil.dll
+// MVID: {B2D2C9A1-63E8-4408-87AE-AD79B08CA2DE}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x00000000001D0000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public sequential ansi sealed import beforefieldinit Struct0
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 30 00 00 ) // ...Struct.0..
+} // end of class Struct0
+
+.class public sequential ansi sealed import beforefieldinit Struct1
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 31 00 00 ) // ...Struct.1..
+} // end of class Struct1
+
+.class public sequential ansi sealed import beforefieldinit Struct2
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 32 00 00 ) // ...Struct.2..
+} // end of class Struct2
+
+.class public sequential ansi sealed import beforefieldinit Struct3
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 33 00 00 ) // ...Struct.3..
+} // end of class Struct3
+
+.class public sequential ansi sealed import beforefieldinit Struct4
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 34 00 00 ) // ...Struct.4..
+} // end of class Struct4
+
+.class public sequential ansi sealed import beforefieldinit Struct5
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 35 00 00 ) // ...Struct.5..
+} // end of class Struct5
+
+.class public sequential ansi sealed import beforefieldinit Struct6
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 36 00 00 ) // ...Struct.6..
+} // end of class Struct6
+
+.class public sequential ansi sealed import beforefieldinit Struct7
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 37 00 00 ) // ...Struct.7..
+} // end of class Struct7
+
+.class public sequential ansi sealed import beforefieldinit Struct8
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 38 00 00 ) // ...Struct.8..
+} // end of class Struct8
+
+.class public sequential ansi sealed import beforefieldinit Struct9
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 39 00 00 ) // ...Struct.9..
+} // end of class Struct9
+
+.class public sequential ansi sealed import beforefieldinit Struct10
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 30 00 00 ) // ...Struct.10..
+} // end of class Struct10
+
+.class public sequential ansi sealed import beforefieldinit Struct11
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 31 00 00 ) // ...Struct.11..
+} // end of class Struct11
+
+.class public sequential ansi sealed import beforefieldinit Struct12
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 32 00 00 ) // ...Struct.12..
+} // end of class Struct12
+
+.class public sequential ansi sealed import beforefieldinit Struct13
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 33 00 00 ) // ...Struct.13..
+} // end of class Struct13
+
+.class public sequential ansi sealed import beforefieldinit Struct14
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 34 00 00 ) // ...Struct.14..
+} // end of class Struct14
+
+.class public sequential ansi sealed import beforefieldinit Struct15
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 35 00 00 ) // ...Struct.15..
+} // end of class Struct15
+
+.class public sequential ansi sealed import beforefieldinit Struct16
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 36 00 00 ) // ...Struct.16..
+} // end of class Struct16
+
+.class public sequential ansi sealed import beforefieldinit Struct17
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 37 00 00 ) // ...Struct.17..
+} // end of class Struct17
+
+.class public sequential ansi sealed import beforefieldinit Struct18
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 38 00 00 ) // ...Struct.18..
+} // end of class Struct18
+
+.class public sequential ansi sealed import beforefieldinit Struct19
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 39 00 00 ) // ...Struct.19..
+} // end of class Struct19
+
+.class public sequential ansi sealed import beforefieldinit Struct20
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 30 00 00 ) // ...Struct.20..
+} // end of class Struct20
+
+.class public sequential ansi sealed import beforefieldinit Struct21
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 31 00 00 ) // ...Struct.21..
+} // end of class Struct21
+
+.class public sequential ansi sealed import beforefieldinit Struct22
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 32 00 00 ) // ...Struct.22..
+} // end of class Struct22
+
+.class public sequential ansi sealed import beforefieldinit Struct23
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 33 00 00 ) // ...Struct.23..
+} // end of class Struct23
+
+.class public sequential ansi sealed import beforefieldinit Struct24
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 34 00 00 ) // ...Struct.24..
+} // end of class Struct24
+
+.class public sequential ansi sealed import beforefieldinit Struct25
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 35 00 00 ) // ...Struct.25..
+} // end of class Struct25
+
+.class public sequential ansi sealed import beforefieldinit Struct26
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 36 00 00 ) // ...Struct.26..
+} // end of class Struct26
+
+.class public sequential ansi sealed import beforefieldinit Struct27
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 37 00 00 ) // ...Struct.27..
+} // end of class Struct27
+
+.class public sequential ansi sealed import beforefieldinit Struct28
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 38 00 00 ) // ...Struct.28..
+} // end of class Struct28
+
+.class public sequential ansi sealed import beforefieldinit Struct29
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 39 00 00 ) // ...Struct.29..
+} // end of class Struct29
+
+.class interface public abstract auto import ansi EquivalentInterface3
+{
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 09 49 6E 74 65 72 66 61 63 65 01 33 00 00 ) // ...Interface.3..
+ .method public hidebysig newslot abstract virtual
+ instance valuetype Struct6 InterfaceFunction(valuetype Struct7 param) cil managed
+ {
+ } // end of method EquivalentInterface3::InterfaceFunction
+
+} // end of class EquivalentInterface3
+
+
+
+
+.class interface public abstract auto ansi TargetInterface8
+{
+ .method public hidebysig newslot abstract virtual
+ instance valuetype Struct16 InterfaceFunction<T>(valuetype Struct17 param,
+ !!T otherParam) cil managed
+ {
+ } // end of method TargetInterface8::InterfaceFunction
+
+} // end of class TargetInterface8
+
+.class public auto ansi beforefieldinit TargetClassTest2_Base
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig newslot virtual
+ instance valuetype Struct4 VirtualFunction(valuetype Struct5 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct4 V_0,
+ valuetype Struct4 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct4
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest2_Base::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest2_Base::.ctor
+
+} // end of class TargetClassTest2_Base
+
+.class public auto ansi beforefieldinit TargetClassTest6_Base
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig newslot virtual
+ instance valuetype Struct12 VirtualFunction<T>(valuetype Struct13 param,
+ !!T paramOther) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct12 V_0,
+ valuetype Struct12 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct12
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest6_Base::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest6_Base::.ctor
+
+} // end of class TargetClassTest6_Base
+
+.class public auto ansi beforefieldinit TargetClassTest7_Base
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig newslot virtual
+ instance valuetype Struct14 VirtualFunction<T>(valuetype Struct15 param,
+ !!T paramOther) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct14 V_0,
+ valuetype Struct14 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct14
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest7_Base::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest7_Base::.ctor
+
+} // end of class TargetClassTest7_Base
+
+.class public auto ansi beforefieldinit TargetClassTest10_Base
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig newslot virtual
+ instance vararg valuetype Struct20
+ VarargFunction(valuetype Struct21 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct20 V_0,
+ valuetype Struct20 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct20
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest10_Base::VarargFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest10_Base::.ctor
+
+} // end of class TargetClassTest10_Base
+
+
+.class public auto ansi beforefieldinit TargetClassTest11_Base
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig newslot virtual
+ instance valuetype Struct22 VirtualFunction(valuetype Struct23 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct22 V_0,
+ valuetype Struct22 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct22
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest11_Base::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest11_Base::.ctor
+
+} // end of class TargetClassTest11_Base
+
+.class public auto ansi beforefieldinit TargetClassTest12_Base
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig newslot virtual
+ instance valuetype Struct24 VirtualFunction(valuetype Struct25 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct24 V_0,
+ valuetype Struct24 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct24
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest12_Base::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest12_Base::.ctor
+
+} // end of class TargetClassTest12_Base
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file foo.res
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk.IL">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <CLRTestKind>SharedLibrary</CLRTestKind>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="basetestclassesil.il" />
+ </ItemGroup>
+</Project>
--- /dev/null
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.20326.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.AMD64chk
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly extern testclassesil
+{
+ .ver 0:0:0:0
+}
+.assembly extern basetestclassesil
+{
+ .ver 0:0:0:0
+}
+.assembly nopiatestil
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module NoPiaTestIL.exe
+// MVID: {B2D2C9A1-63E8-4408-87AE-AD79B08CA2DE}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x00000000001D0000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public sequential ansi sealed import beforefieldinit Struct0
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 30 00 00 ) // ...Struct.0..
+} // end of class Struct0
+
+.class public sequential ansi sealed import beforefieldinit Struct1
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 31 00 00 ) // ...Struct.1..
+} // end of class Struct1
+
+.class public sequential ansi sealed import beforefieldinit Struct2
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 32 00 00 ) // ...Struct.2..
+} // end of class Struct2
+
+.class public sequential ansi sealed import beforefieldinit Struct3
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 33 00 00 ) // ...Struct.3..
+} // end of class Struct3
+
+.class public sequential ansi sealed import beforefieldinit Struct4
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 34 00 00 ) // ...Struct.4..
+} // end of class Struct4
+
+.class public sequential ansi sealed import beforefieldinit Struct5
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 35 00 00 ) // ...Struct.5..
+} // end of class Struct5
+
+.class public sequential ansi sealed import beforefieldinit Struct6
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 36 00 00 ) // ...Struct.6..
+} // end of class Struct6
+
+.class public sequential ansi sealed import beforefieldinit Struct7
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 37 00 00 ) // ...Struct.7..
+} // end of class Struct7
+
+.class public sequential ansi sealed import beforefieldinit Struct8
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 38 00 00 ) // ...Struct.8..
+} // end of class Struct8
+
+.class public sequential ansi sealed import beforefieldinit Struct9
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 39 00 00 ) // ...Struct.9..
+} // end of class Struct9
+
+.class public sequential ansi sealed import beforefieldinit Struct10
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 30 00 00 ) // ...Struct.10..
+} // end of class Struct10
+
+.class public sequential ansi sealed import beforefieldinit Struct11
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 31 00 00 ) // ...Struct.11..
+} // end of class Struct11
+
+.class public sequential ansi sealed import beforefieldinit Struct12
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 32 00 00 ) // ...Struct.12..
+} // end of class Struct12
+
+.class public sequential ansi sealed import beforefieldinit Struct13
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 33 00 00 ) // ...Struct.13..
+} // end of class Struct13
+
+.class public sequential ansi sealed import beforefieldinit Struct14
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 34 00 00 ) // ...Struct.14..
+} // end of class Struct14
+
+.class public sequential ansi sealed import beforefieldinit Struct15
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 35 00 00 ) // ...Struct.15..
+} // end of class Struct15
+
+.class public sequential ansi sealed import beforefieldinit Struct16
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 36 00 00 ) // ...Struct.16..
+} // end of class Struct16
+
+.class public sequential ansi sealed import beforefieldinit Struct17
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 37 00 00 ) // ...Struct.17..
+} // end of class Struct17
+
+.class public sequential ansi sealed import beforefieldinit Struct18
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 38 00 00 ) // ...Struct.18..
+} // end of class Struct18
+
+.class public sequential ansi sealed import beforefieldinit Struct19
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 39 00 00 ) // ...Struct.19..
+} // end of class Struct19
+
+.class public sequential ansi sealed import beforefieldinit Struct20
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 30 00 00 ) // ...Struct.20..
+} // end of class Struct20
+
+.class public sequential ansi sealed import beforefieldinit Struct21
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 31 00 00 ) // ...Struct.21..
+} // end of class Struct21
+
+.class public sequential ansi sealed import beforefieldinit Struct22
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 32 00 00 ) // ...Struct.22..
+} // end of class Struct22
+
+.class public sequential ansi sealed import beforefieldinit Struct23
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 33 00 00 ) // ...Struct.23..
+} // end of class Struct23
+
+.class public sequential ansi sealed import beforefieldinit Struct24
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 34 00 00 ) // ...Struct.24..
+} // end of class Struct24
+
+.class public sequential ansi sealed import beforefieldinit Struct25
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 35 00 00 ) // ...Struct.25..
+} // end of class Struct25
+
+.class public sequential ansi sealed import beforefieldinit Struct26
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 36 00 00 ) // ...Struct.26..
+} // end of class Struct26
+
+.class public sequential ansi sealed import beforefieldinit Struct27
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 37 00 00 ) // ...Struct.27..
+} // end of class Struct27
+
+.class public sequential ansi sealed import beforefieldinit Struct28
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 38 00 00 ) // ...Struct.28..
+} // end of class Struct28
+
+.class public sequential ansi sealed import beforefieldinit Struct29
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 39 00 00 ) // ...Struct.29..
+} // end of class Struct29
+
+.class interface public abstract auto import ansi EquivalentInterface3
+{
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 09 49 6E 74 65 72 66 61 63 65 01 33 00 00 ) // ...Interface.3..
+ .method public hidebysig newslot abstract virtual
+ instance valuetype Struct6 InterfaceFunction(valuetype Struct7 param) cil managed
+ {
+ } // end of method EquivalentInterface3::InterfaceFunction
+
+} // end of class EquivalentInterface3
+
+
+.class public auto ansi sealed Test13Delegate
+ extends [mscorlib]System.MulticastDelegate
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor(object 'object',
+ native int 'method') runtime managed
+ {
+ } // end of method Test13Delegate::.ctor
+
+ .method public hidebysig newslot virtual
+ instance valuetype Struct26 Invoke(valuetype Struct27 param) runtime managed
+ {
+ } // end of method Test13Delegate::Invoke
+
+ .method public hidebysig newslot virtual
+ instance class [mscorlib]System.IAsyncResult
+ BeginInvoke(valuetype Struct27 param,
+ class [mscorlib]System.AsyncCallback callback,
+ object 'object') runtime managed
+ {
+ } // end of method Test13Delegate::BeginInvoke
+
+ .method public hidebysig newslot virtual
+ instance valuetype Struct26 EndInvoke(class [mscorlib]System.IAsyncResult result) runtime managed
+ {
+ } // end of method Test13Delegate::EndInvoke
+
+} // end of class Test13Delegate
+
+.class public auto ansi sealed Test14Delegate
+ extends [mscorlib]System.MulticastDelegate
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor(object 'object',
+ native int 'method') runtime managed
+ {
+ } // end of method Test14Delegate::.ctor
+
+ .method public hidebysig newslot virtual
+ instance valuetype Struct28 Invoke(valuetype Struct29 param) runtime managed
+ {
+ } // end of method Test14Delegate::Invoke
+
+ .method public hidebysig newslot virtual
+ instance class [mscorlib]System.IAsyncResult
+ BeginInvoke(valuetype Struct29 param,
+ class [mscorlib]System.AsyncCallback callback,
+ object 'object') runtime managed
+ {
+ } // end of method Test14Delegate::BeginInvoke
+
+ .method public hidebysig newslot virtual
+ instance valuetype Struct28 EndInvoke(class [mscorlib]System.IAsyncResult result) runtime managed
+ {
+ } // end of method Test14Delegate::EndInvoke
+
+} // end of class Test14Delegate
+
+.class public auto ansi beforefieldinit NoPIATest.Program
+ extends [mscorlib]System.Object
+{
+ .method private hidebysig static void Test1_0() cil managed noinlining
+ {
+ // Code size 28 (0x1c)
+ .maxstack 1
+ .locals init (valuetype Struct1 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... regular c"
+ + "all to static method"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldloca.s V_0
+ IL_000e: initobj Struct1
+ IL_0014: ldloc.0
+ IL_0015: call valuetype Struct0 [testclassesil]TargetClassTest1_0::NormalFunction1(valuetype Struct1)
+ IL_001a: pop
+ IL_001b: ret
+ } // end of method Program::Test1_0
+
+ .method private hidebysig static void Test1_1() cil managed noinlining
+ {
+ // Code size 35 (0x23)
+ .maxstack 2
+ .locals init (class [testclassesil]TargetClassTest1_1 V_0,
+ valuetype Struct3 V_1)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... regular c"
+ + "all to instance method"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: newobj instance void [testclassesil]TargetClassTest1_1::.ctor()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: ldloca.s V_1
+ IL_0015: initobj Struct3
+ IL_001b: ldloc.1
+ IL_001c: callvirt instance valuetype Struct2 [testclassesil]TargetClassTest1_1::NormalFunction1(valuetype Struct3)
+ IL_0021: pop
+ IL_0022: ret
+ } // end of method Program::Test1_1
+
+ .method private hidebysig static class [testclassesil]TargetClassTest2
+ GetTest2Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest2 V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void [testclassesil]TargetClassTest2::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest2Object
+
+ .method private hidebysig static void Test2() cil managed noinlining
+ {
+ // Code size 35 (0x23)
+ .maxstack 2
+ .locals init (class [testclassesil]TargetClassTest2 V_0,
+ valuetype Struct5 V_1)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... virtual c"
+ + "all"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: call class [testclassesil]TargetClassTest2 NoPIATest.Program::GetTest2Object()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: ldloca.s V_1
+ IL_0015: initobj Struct5
+ IL_001b: ldloc.1
+ IL_001c: callvirt instance valuetype Struct4 [basetestclassesil]TargetClassTest2_Base::VirtualFunction(valuetype Struct5)
+ IL_0021: pop
+ IL_0022: ret
+ } // end of method Program::Test2
+
+ .method private hidebysig static class [testclassesil]TargetClassTest3
+ GetTest3Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest3 V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void [testclassesil]TargetClassTest3::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest3Object
+
+ .method private hidebysig static void Test3() cil managed noinlining
+ {
+ // Code size 35 (0x23)
+ .maxstack 2
+ .locals init (class EquivalentInterface3 V_0,
+ valuetype Struct7 V_1)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... interface"
+ + " call"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: call class [testclassesil]TargetClassTest3 NoPIATest.Program::GetTest3Object()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: ldloca.s V_1
+ IL_0015: initobj Struct7
+ IL_001b: ldloc.1
+ IL_001c: callvirt instance valuetype Struct6 EquivalentInterface3::InterfaceFunction(valuetype Struct7)
+ IL_0021: pop
+ IL_0022: ret
+ } // end of method Program::Test3
+
+ .method private hidebysig static void Test4() cil managed noinlining
+ {
+ // Code size 33 (0x21)
+ .maxstack 2
+ .locals init (valuetype Struct9 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... generic c"
+ + "all instantiated over object"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldloca.s V_0
+ IL_000e: initobj Struct9
+ IL_0014: ldloc.0
+ IL_0015: newobj instance void [mscorlib]System.Object::.ctor()
+ IL_001a: call valuetype Struct8 [testclassesil]TargetClassTest4::GenericFunction<object>(valuetype Struct9,
+ !!0)
+ IL_001f: pop
+ IL_0020: ret
+ } // end of method Program::Test4
+
+ .method private hidebysig static class [testclassesil]TargetClassTest5
+ GetTest5Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest5 V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void [testclassesil]TargetClassTest5::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest5Object
+
+ .method private hidebysig static void Test5() cil managed noinlining
+ {
+ // Code size 36 (0x24)
+ .maxstack 3
+ .locals init (class [testclassesil]TargetClassTest5 V_0,
+ valuetype Struct11 V_1)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... generic c"
+ + "all instantiated over int"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: call class [testclassesil]TargetClassTest5 NoPIATest.Program::GetTest5Object()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: ldloca.s V_1
+ IL_0015: initobj Struct11
+ IL_001b: ldloc.1
+ IL_001c: ldc.i4.1
+ IL_001d: callvirt instance valuetype Struct10 [testclassesil]TargetClassTest5::GenericFunction<int32>(valuetype Struct11,
+ !!0)
+ IL_0022: pop
+ IL_0023: ret
+ } // end of method Program::Test5
+
+ .method private hidebysig static class [testclassesil]TargetClassTest6
+ GetTest6Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest6 V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void [testclassesil]TargetClassTest6::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest6Object
+
+ .method private hidebysig static void Test6() cil managed noinlining
+ {
+ // Code size 40 (0x28)
+ .maxstack 3
+ .locals init (class [testclassesil]TargetClassTest6 V_0,
+ valuetype Struct13 V_1)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... generic v"
+ + "irtual call instantiated over object"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: call class [testclassesil]TargetClassTest6 NoPIATest.Program::GetTest6Object()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: ldloca.s V_1
+ IL_0015: initobj Struct13
+ IL_001b: ldloc.1
+ IL_001c: newobj instance void [mscorlib]System.Object::.ctor()
+ IL_0021: callvirt instance valuetype Struct12 [basetestclassesil]TargetClassTest6_Base::VirtualFunction<object>(valuetype Struct13,
+ !!0)
+ IL_0026: pop
+ IL_0027: ret
+ } // end of method Program::Test6
+
+ .method private hidebysig static class [testclassesil]TargetClassTest7
+ GetTest7Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest7 V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void [testclassesil]TargetClassTest7::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest7Object
+
+ .method private hidebysig static void Test7() cil managed noinlining
+ {
+ // Code size 40 (0x28)
+ .maxstack 3
+ .locals init (class [testclassesil]TargetClassTest7 V_0,
+ valuetype Struct15 V_1)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... generic v"
+ + "irtual call instantiated over int"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: call class [testclassesil]TargetClassTest7 NoPIATest.Program::GetTest7Object()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: ldloca.s V_1
+ IL_0015: initobj Struct15
+ IL_001b: ldloc.1
+ IL_001c: newobj instance void [mscorlib]System.Object::.ctor()
+ IL_0021: callvirt instance valuetype Struct14 [basetestclassesil]TargetClassTest7_Base::VirtualFunction<object>(valuetype Struct15,
+ !!0)
+ IL_0026: pop
+ IL_0027: ret
+ } // end of method Program::Test7
+
+ .method private hidebysig static class [testclassesil]TargetClassTest8
+ GetTest8Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest8 V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void [testclassesil]TargetClassTest8::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest8Object
+
+ .method private hidebysig static void Test8() cil managed noinlining
+ {
+ // Code size 40 (0x28)
+ .maxstack 3
+ .locals init (class [testclassesil]TargetInterface8 V_0,
+ valuetype Struct17 V_1)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... generic i"
+ + "nterface call instantiated over object"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: call class [testclassesil]TargetClassTest8 NoPIATest.Program::GetTest8Object()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: ldloca.s V_1
+ IL_0015: initobj Struct17
+ IL_001b: ldloc.1
+ IL_001c: newobj instance void [mscorlib]System.Object::.ctor()
+ IL_0021: callvirt instance valuetype Struct16 [testclassesil]TargetInterface8::InterfaceFunction<object>(valuetype Struct17,
+ !!0)
+ IL_0026: pop
+ IL_0027: ret
+ } // end of method Program::Test8
+
+ .method private hidebysig static class [testclassesil]TargetClassTest9
+ GetTest9Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest9 V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void [testclassesil]TargetClassTest9::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest9Object
+
+ .method private hidebysig static void Test9() cil managed noinlining
+ {
+ // Code size 70 (0x46)
+ .maxstack 5
+ .locals init (class [testclassesil]TargetClassTest9 V_0,
+ valuetype Struct19 V_1,
+ valuetype [mscorlib]System.DateTime V_2)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... varargs c"
+ + "all"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: call class [testclassesil]TargetClassTest9 NoPIATest.Program::GetTest9Object()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: ldloca.s V_1
+ IL_0015: initobj Struct19
+ IL_001b: ldloc.1
+ IL_001c: callvirt instance vararg valuetype Struct18 [testclassesil]TargetClassTest9::VarargFunction(valuetype Struct19)
+ IL_0021: pop
+ IL_0022: ldloc.0
+ IL_0023: ldloca.s V_1
+ IL_0025: initobj Struct19
+ IL_002b: ldloc.1
+ IL_002c: newobj instance void [mscorlib]System.Object::.ctor()
+ IL_0031: ldloca.s V_2
+ IL_0033: initobj [mscorlib]System.DateTime
+ IL_0039: ldloc.2
+ IL_003a: newobj instance void [mscorlib]System.Object::.ctor()
+ IL_003f: callvirt instance vararg valuetype Struct18 [testclassesil]TargetClassTest9::VarargFunction(valuetype Struct19,
+ ...,
+ object,
+ valuetype [mscorlib]System.DateTime,
+ object)
+ IL_0044: pop
+ IL_0045: ret
+ } // end of method Program::Test9
+
+ .method private hidebysig static class [testclassesil]TargetClassTest10
+ GetTest10Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest10 V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void [testclassesil]TargetClassTest10::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest10Object
+
+ .method private hidebysig static void Test10() cil managed noinlining
+ {
+ // Code size 70 (0x46)
+ .maxstack 5
+ .locals init (class [testclassesil]TargetClassTest10 V_0,
+ valuetype Struct21 V_1,
+ valuetype [mscorlib]System.DateTime V_2)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... virtual v"
+ + "arargs call"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: call class [testclassesil]TargetClassTest10 NoPIATest.Program::GetTest10Object()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: ldloca.s V_1
+ IL_0015: initobj Struct21
+ IL_001b: ldloc.1
+ IL_001c: callvirt instance vararg valuetype Struct20 [basetestclassesil]TargetClassTest10_Base::VarargFunction(valuetype Struct21)
+ IL_0021: pop
+ IL_0022: ldloc.0
+ IL_0023: ldloca.s V_1
+ IL_0025: initobj Struct21
+ IL_002b: ldloc.1
+ IL_002c: newobj instance void [mscorlib]System.Object::.ctor()
+ IL_0031: ldloca.s V_2
+ IL_0033: initobj [mscorlib]System.DateTime
+ IL_0039: ldloc.2
+ IL_003a: newobj instance void [mscorlib]System.Object::.ctor()
+ IL_003f: callvirt instance vararg valuetype Struct20 [basetestclassesil]TargetClassTest10_Base::VarargFunction(valuetype Struct21,
+ ...,
+ object,
+ valuetype [mscorlib]System.DateTime,
+ object)
+ IL_0044: pop
+ IL_0045: ret
+ } // end of method Program::Test10
+
+ .method private hidebysig static class [testclassesil]TargetClassTest11`1<object>
+ GetTest11Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest11`1<object> V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void class [testclassesil]TargetClassTest11`1<object>::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest11Object
+
+ .method private hidebysig static void Test11() cil managed noinlining
+ {
+ // Code size 46 (0x2e)
+ .maxstack 2
+ .locals init (class [testclassesil]TargetClassTest11`1<object> V_0,
+ valuetype Struct23 V_1)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... virtual c"
+ + "all ... method defined on generic type instantiated over object"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldstr "return and parameter value equivalent... virtual c"
+ + "all"
+ IL_0011: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0016: nop
+ IL_0017: call class [testclassesil]TargetClassTest11`1<object> NoPIATest.Program::GetTest11Object()
+ IL_001c: stloc.0
+ IL_001d: ldloc.0
+ IL_001e: ldloca.s V_1
+ IL_0020: initobj Struct23
+ IL_0026: ldloc.1
+ IL_0027: callvirt instance valuetype Struct22 [basetestclassesil]TargetClassTest11_Base::VirtualFunction(valuetype Struct23)
+ IL_002c: pop
+ IL_002d: ret
+ } // end of method Program::Test11
+
+ .method private hidebysig static class [testclassesil]TargetClassTest12`1<int32>
+ GetTest12Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest12`1<int32> V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void class [testclassesil]TargetClassTest12`1<int32>::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest12Object
+
+ .method private hidebysig static void Test12() cil managed noinlining
+ {
+ // Code size 46 (0x2e)
+ .maxstack 2
+ .locals init (class [testclassesil]TargetClassTest12`1<int32> V_0,
+ valuetype Struct25 V_1)
+ IL_0000: nop
+ IL_0001: ldstr "return and parameter value equivalent... virtual c"
+ + "all ... method defined on generic type instantiated over int"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldstr "return and parameter value equivalent... virtual c"
+ + "all"
+ IL_0011: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0016: nop
+ IL_0017: call class [testclassesil]TargetClassTest12`1<int32> NoPIATest.Program::GetTest12Object()
+ IL_001c: stloc.0
+ IL_001d: ldloc.0
+ IL_001e: ldloca.s V_1
+ IL_0020: initobj Struct25
+ IL_0026: ldloc.1
+ IL_0027: callvirt instance valuetype Struct24 [basetestclassesil]TargetClassTest12_Base::VirtualFunction(valuetype Struct25)
+ IL_002c: pop
+ IL_002d: ret
+ } // end of method Program::Test12
+
+ .method private hidebysig static void Test13() cil managed noinlining
+ {
+ // Code size 68 (0x44)
+ .maxstack 3
+ .locals init (class Test13Delegate V_0,
+ class Test13Delegate V_1,
+ class Test13Delegate V_2,
+ valuetype Struct27 V_3)
+ IL_0000: nop
+ IL_0001: ldstr "Calling a multicast delegate to a non-virtual meth"
+ + "od constructed with an equivalent method"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldnull
+ IL_000d: ldftn valuetype Struct26 [testclassesil]TargetClassTest13::NormalFunction(valuetype Struct27)
+ IL_0013: newobj instance void Test13Delegate::.ctor(object,
+ native int)
+ IL_0018: stloc.0
+ IL_0019: ldnull
+ IL_001a: ldftn valuetype Struct26 [testclassesil]TargetClassTest13::NormalFunction(valuetype Struct27)
+ IL_0020: newobj instance void Test13Delegate::.ctor(object,
+ native int)
+ IL_0025: stloc.1
+ IL_0026: ldloc.0
+ IL_0027: ldloc.1
+ IL_0028: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
+ class [mscorlib]System.Delegate)
+ IL_002d: castclass Test13Delegate
+ IL_0032: stloc.2
+ IL_0033: ldloc.2
+ IL_0034: ldloca.s V_3
+ IL_0036: initobj Struct27
+ IL_003c: ldloc.3
+ IL_003d: callvirt instance valuetype Struct26 Test13Delegate::Invoke(valuetype Struct27)
+ IL_0042: pop
+ IL_0043: ret
+ } // end of method Program::Test13
+
+ .method private hidebysig static class [testclassesil]TargetClassTest14
+ GetTest14Object() cil managed noinlining
+ {
+ // Code size 11 (0xb)
+ .maxstack 1
+ .locals init (class [testclassesil]TargetClassTest14 V_0)
+ IL_0000: nop
+ IL_0001: newobj instance void [testclassesil]TargetClassTest14::.ctor()
+ IL_0006: stloc.0
+ IL_0007: br.s IL_0009
+
+ IL_0009: ldloc.0
+ IL_000a: ret
+ } // end of method Program::GetTest14Object
+
+ .method private hidebysig static void Test14() cil managed noinlining
+ {
+ // Code size 78 (0x4e)
+ .maxstack 3
+ .locals init (class Test14Delegate V_0,
+ class Test14Delegate V_1,
+ class Test14Delegate V_2,
+ valuetype Struct29 V_3)
+ IL_0000: nop
+ IL_0001: ldstr "Calling a multicast delegate to a virtual method c"
+ + "onstructed with an equivalent method"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: call class [testclassesil]TargetClassTest14 NoPIATest.Program::GetTest14Object()
+ IL_0011: dup
+ IL_0012: ldvirtftn instance valuetype Struct28 [testclassesil]TargetClassTest14::VirtualFunction(valuetype Struct29)
+ IL_0018: newobj instance void Test14Delegate::.ctor(object,
+ native int)
+ IL_001d: stloc.0
+ IL_001e: call class [testclassesil]TargetClassTest14 NoPIATest.Program::GetTest14Object()
+ IL_0023: dup
+ IL_0024: ldvirtftn instance valuetype Struct28 [testclassesil]TargetClassTest14::VirtualFunction(valuetype Struct29)
+ IL_002a: newobj instance void Test14Delegate::.ctor(object,
+ native int)
+ IL_002f: stloc.1
+ IL_0030: ldloc.0
+ IL_0031: ldloc.1
+ IL_0032: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
+ class [mscorlib]System.Delegate)
+ IL_0037: castclass Test14Delegate
+ IL_003c: stloc.2
+ IL_003d: ldloc.2
+ IL_003e: ldloca.s V_3
+ IL_0040: initobj Struct29
+ IL_0046: ldloc.3
+ IL_0047: callvirt instance valuetype Struct28 Test14Delegate::Invoke(valuetype Struct29)
+ IL_004c: pop
+ IL_004d: ret
+ } // end of method Program::Test14
+
+ .method private hidebysig static int32 Main(string[] args) cil managed noinlining
+ {
+ .entrypoint
+ // Code size 249 (0xf9)
+ .maxstack 2
+ .locals init ([0] int32 start,
+ [1] int32 end,
+ [2] int32 iter,
+ [3] bool CS$4$0000,
+ [4] int32 CS$4$0001)
+ IL_0000: nop
+ IL_0001: ldc.i4.0
+ IL_0002: stloc.0
+ IL_0003: ldc.i4.s 14
+ IL_0005: stloc.1
+ IL_0006: ldarg.0
+ IL_0007: ldlen
+ IL_0008: conv.i4
+ IL_0009: ldc.i4.0
+ IL_000a: ceq
+ IL_000c: stloc.3
+ IL_000d: ldloc.3
+ IL_000e: brtrue.s IL_001d
+ IL_0010: nop
+ IL_0011: ldarg.0
+ IL_0012: ldc.i4.0
+ IL_0013: ldelem.ref
+ IL_0014: call int32 [mscorlib]System.Int32::Parse(string)
+ IL_0019: dup
+ IL_001a: stloc.1
+ IL_001b: stloc.0
+ IL_001c: nop
+ IL_001d: ldloc.0
+ IL_001e: stloc.2
+ IL_001f: br IL_00ea
+ IL_0024: nop
+ IL_0025: ldloc.2
+ IL_0026: stloc.s CS$4$0001
+ IL_0028: ldloc.s CS$4$0001
+ IL_002a: switch (
+ IL_006d,
+ IL_0075,
+ IL_007d,
+ IL_0085,
+ IL_008d,
+ IL_0095,
+ IL_009d,
+ IL_00a5,
+ IL_00ad,
+ IL_00b5,
+ IL_00bd,
+ IL_00c5,
+ IL_00cd,
+ IL_00d5,
+ IL_00dd)
+ IL_006b: br.s IL_00e5
+ IL_006d: call void NoPIATest.Program::Test1_0()
+ IL_0072: nop
+ IL_0073: br.s IL_00e5
+ IL_0075: call void NoPIATest.Program::Test1_1()
+ IL_007a: nop
+ IL_007b: br.s IL_00e5
+ IL_007d: call void NoPIATest.Program::Test2()
+ IL_0082: nop
+ IL_0083: br.s IL_00e5
+ IL_0085: call void NoPIATest.Program::Test3()
+ IL_008a: nop
+ IL_008b: br.s IL_00e5
+ IL_008d: call void NoPIATest.Program::Test4()
+ IL_0092: nop
+ IL_0093: br.s IL_00e5
+ IL_0095: call void NoPIATest.Program::Test5()
+ IL_009a: nop
+ IL_009b: br.s IL_00e5
+ IL_009d: call void NoPIATest.Program::Test6()
+ IL_00a2: nop
+ IL_00a3: br.s IL_00e5
+ IL_00a5: call void NoPIATest.Program::Test7()
+ IL_00aa: nop
+ IL_00ab: br.s IL_00e5
+ IL_00ad: call void NoPIATest.Program::Test8()
+ IL_00b2: nop
+ IL_00b3: br.s IL_00e5
+ IL_00b5: call void NoPIATest.Program::Test9()
+ IL_00ba: nop
+ IL_00bb: br.s IL_00e5
+ IL_00bd: call void NoPIATest.Program::Test10()
+ IL_00c2: nop
+ IL_00c3: br.s IL_00e5
+ IL_00c5: call void NoPIATest.Program::Test11()
+ IL_00ca: nop
+ IL_00cb: br.s IL_00e5
+ IL_00cd: call void NoPIATest.Program::Test12()
+ IL_00d2: nop
+ IL_00d3: br.s IL_00e5
+ IL_00d5: call void NoPIATest.Program::Test13()
+ IL_00da: nop
+ IL_00db: br.s IL_00e5
+ IL_00dd: call void NoPIATest.Program::Test14()
+ IL_00e2: nop
+ IL_00e3: br.s IL_00e5
+ IL_00e5: nop
+ IL_00e6: ldloc.2
+ IL_00e7: ldc.i4.1
+ IL_00e8: add
+ IL_00e9: stloc.2
+ IL_00ea: ldloc.2
+ IL_00eb: ldloc.1
+ IL_00ec: cgt
+ IL_00ee: ldc.i4.0
+ IL_00ef: ceq
+ IL_00f1: stloc.3
+ IL_00f2: ldloc.3
+ IL_00f3: brtrue IL_0024
+ ldc.i4 100
+ IL_00f8: ret
+
+ } // end of method Program::Main
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Program::.ctor
+
+} // end of class NoPIATest.Program
+
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk.IL">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <MonoAotIncompatible>true</MonoAotIncompatible>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="nopiatestil.il" />
+ <ProjectReference Include="basetestclassesil.ilproj" />
+ <ProjectReference Include="testclassesil.ilproj" />
+ </ItemGroup>
+</Project>
--- /dev/null
+
+// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.20326.0
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+
+// Metadata version: v4.0.AMD64chk
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 4:0:0:0
+}
+.assembly extern basetestclassesil
+{
+ .ver 0:0:0:0
+}
+.assembly testclassesil
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module testclassesil.dll
+// MVID: {B2D2C9A1-63E8-4408-87AE-AD79B08CA2DE}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x00000000001D0000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public sequential ansi sealed import beforefieldinit Struct0
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 30 00 00 ) // ...Struct.0..
+} // end of class Struct0
+
+.class public sequential ansi sealed import beforefieldinit Struct1
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 31 00 00 ) // ...Struct.1..
+} // end of class Struct1
+
+.class public sequential ansi sealed import beforefieldinit Struct2
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 32 00 00 ) // ...Struct.2..
+} // end of class Struct2
+
+.class public sequential ansi sealed import beforefieldinit Struct3
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 33 00 00 ) // ...Struct.3..
+} // end of class Struct3
+
+.class public sequential ansi sealed import beforefieldinit Struct4
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 34 00 00 ) // ...Struct.4..
+} // end of class Struct4
+
+.class public sequential ansi sealed import beforefieldinit Struct5
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 35 00 00 ) // ...Struct.5..
+} // end of class Struct5
+
+.class public sequential ansi sealed import beforefieldinit Struct6
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 36 00 00 ) // ...Struct.6..
+} // end of class Struct6
+
+.class public sequential ansi sealed import beforefieldinit Struct7
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 37 00 00 ) // ...Struct.7..
+} // end of class Struct7
+
+.class public sequential ansi sealed import beforefieldinit Struct8
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 38 00 00 ) // ...Struct.8..
+} // end of class Struct8
+
+.class public sequential ansi sealed import beforefieldinit Struct9
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 01 39 00 00 ) // ...Struct.9..
+} // end of class Struct9
+
+.class public sequential ansi sealed import beforefieldinit Struct10
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 30 00 00 ) // ...Struct.10..
+} // end of class Struct10
+
+.class public sequential ansi sealed import beforefieldinit Struct11
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 31 00 00 ) // ...Struct.11..
+} // end of class Struct11
+
+.class public sequential ansi sealed import beforefieldinit Struct12
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 32 00 00 ) // ...Struct.12..
+} // end of class Struct12
+
+.class public sequential ansi sealed import beforefieldinit Struct13
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 33 00 00 ) // ...Struct.13..
+} // end of class Struct13
+
+.class public sequential ansi sealed import beforefieldinit Struct14
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 34 00 00 ) // ...Struct.14..
+} // end of class Struct14
+
+.class public sequential ansi sealed import beforefieldinit Struct15
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 35 00 00 ) // ...Struct.15..
+} // end of class Struct15
+
+.class public sequential ansi sealed import beforefieldinit Struct16
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 36 00 00 ) // ...Struct.16..
+} // end of class Struct16
+
+.class public sequential ansi sealed import beforefieldinit Struct17
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 37 00 00 ) // ...Struct.17..
+} // end of class Struct17
+
+.class public sequential ansi sealed import beforefieldinit Struct18
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 38 00 00 ) // ...Struct.18..
+} // end of class Struct18
+
+.class public sequential ansi sealed import beforefieldinit Struct19
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 31 39 00 00 ) // ...Struct.19..
+} // end of class Struct19
+
+.class public sequential ansi sealed import beforefieldinit Struct20
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 30 00 00 ) // ...Struct.20..
+} // end of class Struct20
+
+.class public sequential ansi sealed import beforefieldinit Struct21
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 31 00 00 ) // ...Struct.21..
+} // end of class Struct21
+
+.class public sequential ansi sealed import beforefieldinit Struct22
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 32 00 00 ) // ...Struct.22..
+} // end of class Struct22
+
+.class public sequential ansi sealed import beforefieldinit Struct23
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 33 00 00 ) // ...Struct.23..
+} // end of class Struct23
+
+.class public sequential ansi sealed import beforefieldinit Struct24
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 34 00 00 ) // ...Struct.24..
+} // end of class Struct24
+
+.class public sequential ansi sealed import beforefieldinit Struct25
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 35 00 00 ) // ...Struct.25..
+} // end of class Struct25
+
+.class public sequential ansi sealed import beforefieldinit Struct26
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 36 00 00 ) // ...Struct.26..
+} // end of class Struct26
+
+.class public sequential ansi sealed import beforefieldinit Struct27
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 37 00 00 ) // ...Struct.27..
+} // end of class Struct27
+
+.class public sequential ansi sealed import beforefieldinit Struct28
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 38 00 00 ) // ...Struct.28..
+} // end of class Struct28
+
+.class public sequential ansi sealed import beforefieldinit Struct29
+ extends [mscorlib]System.ValueType
+{
+ .pack 0
+ .size 1
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 06 53 74 72 75 63 74 02 32 39 00 00 ) // ...Struct.29..
+} // end of class Struct29
+
+.class interface public abstract auto import ansi EquivalentInterface3
+{
+ .custom instance void [mscorlib]System.Runtime.InteropServices.TypeIdentifierAttribute::.ctor(string,
+ string) = ( 01 00 09 49 6E 74 65 72 66 61 63 65 01 33 00 00 ) // ...Interface.3..
+ .method public hidebysig newslot abstract virtual
+ instance valuetype Struct6 InterfaceFunction(valuetype Struct7 param) cil managed
+ {
+ } // end of method EquivalentInterface3::InterfaceFunction
+
+} // end of class EquivalentInterface3
+
+
+
+
+.class interface public abstract auto ansi TargetInterface8
+{
+ .method public hidebysig newslot abstract virtual
+ instance valuetype Struct16 InterfaceFunction<T>(valuetype Struct17 param,
+ !!T otherParam) cil managed
+ {
+ } // end of method TargetInterface8::InterfaceFunction
+
+} // end of class TargetInterface8
+
+.class public auto ansi beforefieldinit TargetClassTest1_0
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static valuetype Struct0
+ NormalFunction1(valuetype Struct1 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct0 V_0,
+ valuetype Struct0 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct0
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest1_0::NormalFunction1
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest1_0::.ctor
+
+} // end of class TargetClassTest1_0
+
+.class public auto ansi beforefieldinit TargetClassTest1_1
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig instance valuetype Struct2
+ NormalFunction1(valuetype Struct3 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct2 V_0,
+ valuetype Struct2 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct2
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest1_1::NormalFunction1
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest1_1::.ctor
+
+} // end of class TargetClassTest1_1
+
+
+.class public auto ansi beforefieldinit TargetClassTest2
+ extends [basetestclassesil]TargetClassTest2_Base
+{
+ .method public hidebysig virtual instance valuetype Struct4
+ VirtualFunction(valuetype Struct5 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct4 V_0,
+ valuetype Struct4 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct4
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest2::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [basetestclassesil]TargetClassTest2_Base::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest2::.ctor
+
+} // end of class TargetClassTest2
+
+.class public auto ansi beforefieldinit TargetClassTest3
+ extends [mscorlib]System.Object
+ implements EquivalentInterface3
+{
+ .method private hidebysig newslot virtual final
+ instance valuetype Struct6 EquivalentInterface3.InterfaceFunction(valuetype Struct7 param) cil managed
+ {
+ .override EquivalentInterface3::InterfaceFunction
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct6 V_0,
+ valuetype Struct6 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct6
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest3::EquivalentInterface3.InterfaceFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest3::.ctor
+
+} // end of class TargetClassTest3
+
+.class public auto ansi beforefieldinit TargetClassTest4
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static valuetype Struct8
+ GenericFunction<T>(valuetype Struct9 param,
+ !!T otherParam) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct8 V_0,
+ valuetype Struct8 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct8
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest4::GenericFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest4::.ctor
+
+} // end of class TargetClassTest4
+
+.class public auto ansi beforefieldinit TargetClassTest5
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig instance valuetype Struct10
+ GenericFunction<T>(valuetype Struct11 param,
+ !!T otherParam) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct10 V_0,
+ valuetype Struct10 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct10
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest5::GenericFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest5::.ctor
+
+} // end of class TargetClassTest5
+
+.class public auto ansi beforefieldinit TargetClassTest6
+ extends [basetestclassesil]TargetClassTest6_Base
+{
+ .method public hidebysig virtual instance valuetype Struct12
+ VirtualFunction<T>(valuetype Struct13 param,
+ !!T paramOther) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct12 V_0,
+ valuetype Struct12 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct12
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest6::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [basetestclassesil]TargetClassTest6_Base::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest6::.ctor
+
+} // end of class TargetClassTest6
+
+.class public auto ansi beforefieldinit TargetClassTest7
+ extends [basetestclassesil]TargetClassTest7_Base
+{
+ .method public hidebysig virtual instance valuetype Struct14
+ VirtualFunction<T>(valuetype Struct15 param,
+ !!T paramOther) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct14 V_0,
+ valuetype Struct14 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct14
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest7::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [basetestclassesil]TargetClassTest7_Base::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest7::.ctor
+
+} // end of class TargetClassTest7
+
+.class public auto ansi beforefieldinit TargetClassTest8
+ extends [mscorlib]System.Object
+ implements TargetInterface8
+{
+ .method private hidebysig newslot virtual final
+ instance valuetype Struct16 TargetInterface8.InterfaceFunction<T>(valuetype Struct17 param,
+ !!T paramOther) cil managed
+ {
+ .override TargetInterface8::InterfaceFunction
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct16 V_0,
+ valuetype Struct16 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct16
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest8::TargetInterface8.InterfaceFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest8::.ctor
+
+} // end of class TargetClassTest8
+
+.class public auto ansi beforefieldinit TargetClassTest9
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig instance vararg valuetype Struct18
+ VarargFunction(valuetype Struct19 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct18 V_0,
+ valuetype Struct18 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct18
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest9::VarargFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest9::.ctor
+
+} // end of class TargetClassTest9
+
+.class public auto ansi beforefieldinit TargetClassTest10
+ extends [basetestclassesil]TargetClassTest10_Base
+{
+ .method public hidebysig virtual instance vararg valuetype Struct20
+ VarargFunction(valuetype Struct21 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct20 V_0,
+ valuetype Struct20 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct20
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest10::VarargFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [basetestclassesil]TargetClassTest10_Base::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest10::.ctor
+
+} // end of class TargetClassTest10
+
+.class public auto ansi beforefieldinit TargetClassTest11`1<T>
+ extends [basetestclassesil]TargetClassTest11_Base
+{
+ .method public hidebysig virtual instance valuetype Struct22
+ VirtualFunction(valuetype Struct23 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct22 V_0,
+ valuetype Struct22 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct22
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest11`1::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [basetestclassesil]TargetClassTest11_Base::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest11`1::.ctor
+
+} // end of class TargetClassTest11`1
+
+.class public auto ansi beforefieldinit TargetClassTest12`1<T>
+ extends [basetestclassesil]TargetClassTest12_Base
+{
+ .method public hidebysig virtual instance valuetype Struct24
+ VirtualFunction(valuetype Struct25 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct24 V_0,
+ valuetype Struct24 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct24
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest12`1::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [basetestclassesil]TargetClassTest12_Base::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest12`1::.ctor
+
+} // end of class TargetClassTest12`1
+
+.class public auto ansi beforefieldinit TargetClassTest13
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig static valuetype Struct26
+ NormalFunction(valuetype Struct27 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct26 V_0,
+ valuetype Struct26 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct26
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest13::NormalFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest13::.ctor
+
+} // end of class TargetClassTest13
+
+.class public auto ansi beforefieldinit TargetClassTest14
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig newslot virtual
+ instance valuetype Struct28 VirtualFunction(valuetype Struct29 param) cil managed
+ {
+ // Code size 15 (0xf)
+ .maxstack 1
+ .locals init (valuetype Struct28 V_0,
+ valuetype Struct28 V_1)
+ IL_0000: nop
+ IL_0001: ldloca.s V_1
+ IL_0003: initobj Struct28
+ IL_0009: ldloc.1
+ IL_000a: stloc.0
+ IL_000b: br.s IL_000d
+
+ IL_000d: ldloc.0
+ IL_000e: ret
+ } // end of method TargetClassTest14::VirtualFunction
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method TargetClassTest14::.ctor
+
+} // end of class TargetClassTest14
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
+// WARNING: Created Win32 resource file foo.res
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk.IL">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <CLRTestKind>SharedLibrary</CLRTestKind>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="testclassesil.il" />
+ </ItemGroup>
+</Project>
<ExcludeList Include="$(XunitTestBinBase)/tracing/eventpipe/eventsourceerror/eventsourceerror/*">
<Issue>https://github.com/dotnet/runtime/issues/80666</Issue>
</ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/signatures/nopiatestil/*">
+ <Issue>CoreCLR doesn't support type equivalence on Unix</Issue>
+ </ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/istypeequivalent/istypeequivalent/*">
+ <Issue>CoreCLR doesn't support type equivalence on Unix</Issue>
+ </ExcludeList>
</ItemGroup>
<!-- Arm32 All OS -->
<ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/simple/Simple/*">
<Issue>https://github.com/dotnet/runtimelab/issues/155: Type equivalence</Issue>
</ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/signatures/nopiatestil/*">
+ <Issue>https://github.com/dotnet/runtimelab/issues/155: Type equivalence</Issue>
+ </ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/istypeequivalent/istypeequivalent/*">
+ <Issue>https://github.com/dotnet/runtimelab/issues/155: Type equivalence</Issue>
+ </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/GC/API/WeakReference/Finalize2/*">
<Issue>Expectations about finalization order</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/simple/Simple/*">
<Issue>Mono doesn't support type equivalence on types implemented in different assemblies</Issue>
</ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/signatures/nopiatestil/*">
+ <Issue>Mono doesn't support type equivalence on types implemented in different assemblies</Issue>
+ </ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/istypeequivalent/istypeequivalent/*">
+ <Issue>Mono doesn't support type equivalence on types implemented in different assemblies</Issue>
+ </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/ArrayMarshalling/SafeArray/SafeArrayTest/*">
<Issue>Requires COM support, disabled on all Mono platforms.</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/simple/Simple/**">
<Issue>Doesn't compile with LLVM AOT.</Issue>
</ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/signatures/nopiatestil/nopiatestil/**">
+ <Issue>Doesn't compile with LLVM AOT.</Issue>
+ </ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/baseservices/typeequivalence/istypeequivalent/istypeequivalent/*">
+ <Issue>Doesn't compile with LLVM AOT.</Issue>
+ </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/generics/Variance/IL/Unbox002/**">
<Issue>Doesn't compile with LLVM AOT.</Issue>
</ExcludeList>